1
! -------------------------------------------------------------------------
2
! Menus.h A library extension providing easier and better menus
5
! A menu is a tree of objects of class Option. A Menu is an Option which
6
! launches a fresh menu when chosen. To choose option O, send the
11
! So to start off a menu session, send this message to the top menu.
13
! Here's a simple menu structure:
15
! Menu "Instructions for playing Mordred";
16
! Menu -> "How to play adventure games";
17
! Option -> -> "Looking around"
18
! with description "I am your eyes and ears ...";
19
! Option -> -> "Taking and Dropping"
20
! with description "When you find items ...";
21
! Option -> "About the author"
22
! with description "The author was born in ...";
24
! Menus produced in this code are automatically divided into pages
25
! so that they'll always fit on the screen, whatever size the screen is
26
! and however many options there are.
28
! Note that since objects can always be moved about in play, it's easy
29
! to create new menu structures to fit the circumstances of the moment.
30
! (For example, a hints menu which gives hints only on currently open
33
! You can instead write a routine to receive the "description" message.
34
! Then the text printed when an option is chosen can also vary.
36
! If you return 2 from such a routine, then the game does not prompt
37
! the player to press a key before going back into the menu.
38
! If you return 3, then the whole menu is closed up immediately.
40
! Finally, you can always give your own "select" routine for an Option.
41
! The rules for return values are the same; what's different is that
42
! this way the screen will not be cleared and given a nice banner when
43
! the option is chosen. (Nothing visible will happen unless you do
44
! it yourself.) The SwitchOption class is an example of the kind of
45
! gadget you might want this for:
47
! Menu "Game settings";
48
! SwitchOption -> FullRoomD "full room descriptions" has on;
49
! SwitchOption -> WordyP "wordier prompts";
50
! SwitchOption -> AllowSavedG "allow saved games" has on;
52
! Choosing any of these switch-options flips them between on and off.
53
! In your program, you can test
55
! if (WordyP has on) ...
57
! and so forth to check the current state.
58
! -------------------------------------------------------------------------
64
! Then we are using library 6/1 or 6/2, which won't have defined these:
66
Constant NKEY__TX = " N = next option";
67
Constant PKEY__TX = "P = previous";
68
Constant QKEY1__TX = " Q = resume game";
69
Constant QKEY2__TX = "Q = previous menu";
70
Constant RKEY__TX = "RETURN = select option";
72
Constant NKEY1__KY = 'N';
73
Constant NKEY2__KY = 'n';
74
Constant PKEY1__KY = 'P';
75
Constant PKEY2__KY = 'p';
76
Constant QKEY1__KY = 'Q';
77
Constant QKEY2__KY = 'q';
84
Array ForUseByOptions string 128;
87
[ bar_height page pages temp;
94
@split_window bar_height;
96
! Black out top line in reverse video:
99
style reverse; spaces(screen_width);
101
if (standard_interpreter == 0)
104
{ ForUseByOptions-->0 = 128;
105
@output_stream 3 ForUseByOptions;
107
if (pages ~= 1) print " [", page, "/", pages, "]";
109
temp = (screen_width - ForUseByOptions-->0)/2;
114
if (pages ~= 1) print " [", page, "/", pages, "]";
116
return ForUseByOptions-->0;
119
[; self.emblazon(1, 1, 1);
121
@set_window 0; font on; style roman; new_line; new_line;
123
if (self provides description)
124
return self.description();
126
"[No text written for this option.]^";
129
Class Menu class Option
131
[ count j obj pkey line oldline top_line bottom_line
132
page pages options top_option;
134
screen_width = 0->33;
135
screen_height = 0->32;
136
if (screen_height == 0 or 255) screen_height = 18;
137
screen_height = screen_height - 7;
140
objectloop (obj in self && obj ofclass Option) options++;
141
if (options == 0) return 2;
143
pages = 1 + options/screen_height;
153
top_option = (page - 1) * screen_height;
155
self.emblazon(7 + count, page, pages);
157
@set_cursor 2 1; spaces(screen_width);
158
@set_cursor 2 2; print (string) NKEY__TX;
159
j = screen_width-12; @set_cursor 2 j; print (string) PKEY__TX;
161
@set_cursor 3 1; spaces(screen_width);
162
@set_cursor 3 2; print (string) RKEY__TX;
163
j = screen_width-17; @set_cursor 3 j;
165
if (sender ofclass Option)
166
print (string) QKEY2__TX;
168
print (string) QKEY1__TX;
171
count = top_line; j = 0;
172
objectloop (obj in self && obj ofclass Option)
173
{ if (j >= top_option && j < (top_option + screen_height))
174
{ @set_cursor count 6;
180
bottom_line = count - 1;
184
{ ! Move or create the > cursor:
187
{ if (oldline~=0) { @set_cursor oldline 4; print " "; }
188
@set_cursor line 4; print ">";
192
@read_char 1 -> pkey;
194
if (pkey == NKEY1__KY or NKEY2__KY or 130)
197
if (line > bottom_line)
200
{ if (page == pages) page = 1; else page++;
207
if (pkey == PKEY1__KY or PKEY2__KY or 129)
211
{ line = bottom_line;
216
+ (options % screen_height) - 1;
219
{ page--; line = top_line + screen_height - 1;
227
if (pkey==QKEY1__KY or QKEY2__KY or 27 or 131) break;
229
if (pkey==10 or 13 or 132)
231
objectloop (obj in self && obj ofclass Option)
232
{ if (count == top_option + line - top_line) break;
242
print "[Please press SPACE to continue.]^";
244
L__M(##Miscellany, 53);
246
@read_char 1 -> pkey;
253
if (sender ofclass Option) return 2;
255
font on; @set_cursor 1 1;
256
@erase_window $ffff; @set_window 0;
257
new_line; new_line; new_line;
258
if (deadflag==0) <<Look>>;
262
Class SwitchOption class Option
264
[; print (object) self, " ";
265
if (self has on) print "(on)"; else print "(off)";
269
[; if (self has on) give self ~on; else give self on;
273
! ------------------------------------------------------------------------