~ubuntu-branches/ubuntu/vivid/inform/vivid

« back to all changes in this revision

Viewing changes to include/adhints.h

  • Committer: Bazaar Package Importer
  • Author(s): Jan Christoph Nordholz
  • Date: 2008-05-26 22:09:44 UTC
  • mfrom: (2.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080526220944-ba7phz0d1k4vo7wx
Tags: 6.31.1+dfsg-1
* Remove a considerable number of files from the package
  due to unacceptable licensing terms.
* Repair library symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
! -------------------------------------------------------------------------
2
 
! Adaptive Hints for Inform
3
 
! (c) 1995 Michael S. Phillips
4
 
! -------------------------------------------------------------------------
5
 
! Hints Library:  Mar 25, 1996
6
 
! Adaptive Hints library, release 0.92a (960325)
7
 
! -------------------------------------------------------------------------
8
 
! This module is (c) 1996 Michael S. Phillips, but it is freely usable.
9
 
! The author may be reached at: mike@lawlib.wm.edu  as of this release.
10
 
! -------------------------------------------------------------------------
11
 
 
12
 
! -------------------------------------------------------------------------
13
 
! A note about customizing the behavior of the hints system:
14
 
!     A large number of '#ifdef xxx;' '#endif;' pairs are in the file, in
15
 
! order for the author using this hints system to be able to dictate the 
16
 
! exact behavior of the hints system.
17
 
!     Ideally, the definition of these variables would be done by the 
18
 
! declaration of an appropriate Constant (e.g. 'Constant GIVEHINTSONCE;')
19
 
! before including AdHints.h into the game.  This way, the library can be
20
 
! swapped if upgraded in such a manner that it does not require editing
21
 
! in order to preserve the desired behavior.  Each meaningful definition
22
 
! (and its effect) is detailed below.
23
 
! -------------------------------------------------------------------------
24
 
! GIVEHINTSONCE: If defined, this will cause a set of hints to be given by
25
 
! the 'HINT' command once AND ONLY ONCE, and only the first time.
26
 
! Otherwise, the hint(s) will disappear and need to be viewed with 
27
 
! 'REVIEW'.  This is not particularly kind behavior, but it does match
28
 
! the behavior of adhint.t for TADS.  If this and NOHINTREVIEW are both
29
 
! defined, then a given set of hints will appear ONE TIME ONLY and be
30
 
! utterly unretrievable afterwards.
31
 
!Constant GIVEHINTSONCE;
32
 
! -------------------------------------------------------------------------
33
 
! NOHINTREVIEW: If defined, this disables the 'REVIEW' command.  Note that 
34
 
! this only disables the grammar for 'REVIEW', and that ReviewSub() can 
35
 
! still be called by the game if the author so desires (for instance, after 
36
 
! the game is over).
37
 
!Constant NOHINTREVIEW;
38
 
! -------------------------------------------------------------------------
39
 
! REVIEWGIVENONLY: If defined, this causes ONLY those hints which were 
40
 
! actually given to be shown by the 'REVIEW' command.
41
 
!Constant REVIEWGIVENONLY;
42
 
! -------------------------------------------------------------------------
43
 
! SHOWSOLVEDTAG: If defined, the string '(solved)' will appear after each
44
 
! puzzle when 'REVIEW'ing hints if the puzzle has been solved.
45
 
!Constant SHOWSOLVEDTAG;
46
 
! -------------------------------------------------------------------------
47
 
! HINTDEBUG: If defined, this will give extra internal information about
48
 
! what is going on at certain key points of the hints code.  You probably
49
 
! don't want to define this unless you're debugging this particular file.
50
 
!Constant HINTDEBUG; 
51
 
! -------------------------------------------------------------------------
52
 
! HINTDEBUGVERBS: If defined, this allows the various hint debugging verbs
53
 
! (allhints, allpuzzles) to be used.  If HINTDEBUG is defined, these will
54
 
! be available.
55
 
!Constant HINTDEBUGVERBS;
56
 
! -------------------------------------------------------------------------
57
 
 
58
 
#ifdef HINTDEBUG;
59
 
#ifndef HINTDEBUGVERBS;
60
 
Constant HINTDEBUGVERBS;
61
 
#endif;
62
 
#endif;
63
 
 
64
 
Attribute given alias visited;
65
 
Attribute solved alias open;
66
 
Attribute in_menu alias locked;
67
 
 
68
 
Property hint_check;
69
 
Property additive the_hints;
70
 
 
71
 
Global AH_hints_available = 1;
72
 
 
73
 
Global AH_num_pages = 0;
74
 
Global AH_current_page = 0;
75
 
Global AH_hints_per_page = 0;
76
 
 
77
 
! First, we define the 'hint' class
78
 
! When constructing a hint, make certain that it 'does the right thing' and
79
 
! is declared as such a class for appropriate defaults.
80
 
! A hint will have the 'general' attribute set if it is available, and the
81
 
! 'given' attribute (which is aliased to 'visited') if the hint has been
82
 
! used.  Only if it is 'given' or 'solved' (which is aliased to 'open') will 
83
 
! it appear with the REVIEW command.
84
 
 
85
 
Class HintClass
86
 
 has  proper
87
 
 with name "hint";
88
 
 
89
 
Object Hints "hints" !selfobj
90
 
 has   concealed
91
 
 with  name "h,";
92
 
 
93
 
! If you need an AfterPrompt() routine yourself, then call it AfterPrompt2, 
94
 
! and this will automatically call it after updating the hints.
95
 
[ AfterPrompt;
96
 
    AH_UpdateHints();
97
 
#ifdef AfterPrompt2;
98
 
    AfterPrompt2();
99
 
#endif;
100
 
];
101
 
 
102
 
! Okay, a meta-routine which is passed a hint object (well, hopefully :-) )
103
 
! and cycles through the hints.
104
 
[ AH_ShowHints  hintobj i j k die_now hint_number;
105
 
 
106
 
    give hintobj given;
107
 
 
108
 
    print "^Hints for: ", (name) hintobj, "^";
109
 
 
110
 
    i = hintobj.#the_hints / 2;
111
 
 
112
 
    j = 1;
113
 
    hint_number = 1;
114
 
 
115
 
    die_now = 0;
116
 
 
117
 
    print "(Press Q to quit receiving hints, or any other key to continue)^";
118
 
 
119
 
    while (j <= i && die_now==0) {
120
 
        print "^^(", j, "/", i, ") ";
121
 
        print_paddr (hintobj.&the_hints)-->(j-1);
122
 
 
123
 
        if (j ~= i) {
124
 
            @read_char 1 0 0 k;
125
 
            if (k=='Q' or 'q') die_now = 1;
126
 
        }
127
 
        j++;
128
 
        hint_number++;
129
 
    }
130
 
 
131
 
    print "^";
132
 
 
133
 
    if (die_now == 1) return 2;
134
 
 
135
 
    rtrue;
136
 
 
137
 
];
138
 
 
139
 
! Okay, another meta routine, this one blips through all the hints and 
140
 
! calls the hint_check routine for all of them, to reset the solved and
141
 
! available flags.  Note that once the puzzle is solved, it is no longer 
142
 
! run (to speed things up).
143
 
[ AH_UpdateHints i j;
144
 
 
145
 
    objectloop (i in Hints) {
146
 
#ifdef HINTDEBUG;
147
 
        print "Running hint_check for: ", (name) i, "^";
148
 
#endif;
149
 
        if (i hasnt solved) {
150
 
            j = ZRegion(i.hint_check);     ! only run if hint_check routine 
151
 
            if (j==2) PrintOrRun(i,hint_check,2);       ! exists for hint i
152
 
        }
153
 
        if (i has solved) give i ~general;
154
 
    }
155
 
];
156
 
 
157
 
! Okay, some debugging routines (useful stuff for me, but useless for most
158
 
! other people, I suspect).
159
 
#ifdef HINTDEBUGVERBS;
160
 
[ AllPuzzlesSub i;
161
 
    print "All Puzzles with Hints:^";
162
 
    objectloop (i in Hints) {
163
 
        print "    ", (name) i;
164
 
#ifdef SHOWSOLVEDTAG;
165
 
        if (i has solved) print " (solved)";
166
 
#endif;
167
 
        print "^";
168
 
    }
169
 
];
170
 
 
171
 
[ AllHintsSub i ;
172
 
 
173
 
    objectloop (i in Hints) {
174
 
        give i in_menu;
175
 
    }
176
 
 
177
 
    AH_Menu();
178
 
 
179
 
    objectloop (i in Hints) {
180
 
        give i ~in_menu;
181
 
    }
182
 
 
183
 
    rtrue;
184
 
 
185
 
];
186
 
#endif;
187
 
 
188
 
! General use function -- calculates the width of a string
189
 
Array width_calc table 64;
190
 
[ AH_CalcWidth s i j;
191
 
    i = 0->33; if (i==0) i = 80;
192
 
    @output_stream 3 width_calc;
193
 
    print (string) s;
194
 
    @output_stream -3;
195
 
    j = (width_calc-->0)/2;
196
 
    return j;
197
 
];
198
 
 
199
 
! Menu support routine for HintSub
200
 
 
201
 
! display hints
202
 
[ AH_HintPrint i count start stop;
203
 
    print "Hints Available:^";
204
 
    count = 0;
205
 
    if (pretty_flag == 0) {
206
 
        objectloop(i in Hints) {
207
 
            if (i has in_menu) {
208
 
                count++;
209
 
                if (count < 10) { print "^  (", count, ") "; }
210
 
                    else print "^ (", count, ") ";
211
 
                print (name) i;
212
 
#ifdef SHOWSOLVEDTAG;
213
 
                if (i has solved) print " (solved)";
214
 
#endif;
215
 
            } ! in_menu
216
 
        } ! objectloop
217
 
    } ! pretty_flag
218
 
    else {
219
 
        start = AH_hints_per_page * (AH_current_page - 1);
220
 
        stop = start + AH_hints_per_page;
221
 
        if (AH_current_page > 1) print "^     (previous page)";
222
 
        objectloop(i in Hints) {
223
 
            if (i has in_menu) {
224
 
                count++;
225
 
                if (count > start && count <= stop) {
226
 
                    print "^     ", (name) i;
227
 
#ifdef SHOWSOLVEDTAG;
228
 
                    if (i has solved) print " (solved)";
229
 
#endif;
230
 
                } ! start < count <= stop
231
 
            } ! in_menu
232
 
        } ! objectloop
233
 
        if (AH_current_page < AH_num_pages) print "^     (next page)";
234
 
    } ! elseif
235
 
];
236
 
 
237
 
! return titles, widths, and stuff
238
 
[ AH_HintInfo i j count target;
239
 
 
240
 
    count = 0;
241
 
    if (pretty_flag == 0) {
242
 
        objectloop(i in Hints) {
243
 
            if (i has in_menu) {
244
 
                count++;
245
 
                if (count == menu_item) j = i;
246
 
            }
247
 
        }
248
 
    } ! plain
249
 
    else {
250
 
        if (AH_current_page == 1) { target = menu_item; }
251
 
        else {target = ((AH_current_page - 1)*AH_hints_per_page) + menu_item;}
252
 
        objectloop (i in Hints) {
253
 
            if (i has in_menu) {
254
 
                count++;
255
 
                if (count == target) j = i;
256
 
            }
257
 
        }
258
 
        ! take care of setting count for paging
259
 
        if (AH_current_page == 1 && AH_num_pages ~= 1)
260
 
            { count = AH_hints_per_page + 1; }
261
 
        else { 
262
 
            if (AH_current_page == AH_num_pages && AH_num_pages ~= 1)
263
 
                { count = count - ((AH_num_pages-1)*AH_hints_per_page) + 1; }
264
 
            else {
265
 
                if (AH_current_page == 1 && AH_num_pages == 1)
266
 
                    { count = count; }  ! null assignment
267
 
                else { count = AH_hints_per_page + 2; }
268
 
            } ! elseif
269
 
        } ! convoluted elseif
270
 
    } ! pretty
271
 
 
272
 
    if (menu_item == 0) {
273
 
        item_name = "Hints";
274
 
        item_width = AH_CalcWidth(item_name);
275
 
        return count;
276
 
    }
277
 
 
278
 
    item_name = j.short_name;
279
 
    item_width = AH_CalcWidth(j.short_name);
280
 
    rtrue;
281
 
];
282
 
 
283
 
! call appropriate routine for menu
284
 
[ AH_HintMenu i j count target;
285
 
    count = 0;
286
 
    if (pretty_flag == 0) {
287
 
        objectloop (i in Hints) {
288
 
            if (i has in_menu) {
289
 
                count++;
290
 
                if (count == menu_item) j = i;
291
 
            } ! in_menu
292
 
        } ! objectloop
293
 
    } ! pretty_flag
294
 
    else {
295
 
! take care of special cases first:
296
 
        if (AH_current_page == 1) {
297
 
            if (menu_item == (AH_hints_per_page + 1)) {
298
 
                AH_current_page++;
299
 
                DoM_cl = 7;
300
 
                return 2;  ! redraw menu screen
301
 
            }
302
 
        } ! current page
303
 
        else {
304
 
            if (menu_item == 1) {
305
 
                AH_current_page--;
306
 
                DoM_cl = 7;
307
 
                return 2;  ! redraw menu screen
308
 
            }
309
 
            if (menu_item == (AH_hints_per_page + 2)) {
310
 
                AH_current_page++;
311
 
                DoM_cl = 7;
312
 
                return 2;  ! redraw menu screen
313
 
            }
314
 
        } ! elseif
315
 
        j = NULL;
316
 
        if (AH_current_page == 1) { target = menu_item; }
317
 
        else {
318
 
            target = ((AH_current_page - 1) * AH_hints_per_page) 
319
 
                     + menu_item - 1;  ! account for (previous page) option
320
 
        } ! elseif
321
 
        objectloop (i in Hints) {
322
 
            if (i has in_menu) {
323
 
                count++;
324
 
                if (count == target) j = i;
325
 
            } ! in_menu
326
 
        } ! objectloop
327
 
    } ! elseif
328
 
    AH_ShowHints(j);
329
 
    rtrue;
330
 
];
331
 
 
332
 
[ AH_CalcMenu i h count;
333
 
    count = 0;
334
 
    objectloop(i in Hints) {
335
 
        if (i has in_menu) count++;
336
 
    }
337
 
    h = 0->32;
338
 
#ifdef HINTDEBUG_PAGING;
339
 
    print "^height: ", h, "^";
340
 
#endif;
341
 
    if (h == 0) h = 25;
342
 
    h = h - 13;         ! adjust for administrative headaches
343
 
    AH_num_pages = (count / h) + 1;
344
 
    AH_hints_per_page = h;
345
 
#ifdef HINTDEBUG_PAGING;
346
 
    print "^num pages: ", AH_num_pages;
347
 
    print "^hints per page: ", AH_hints_per_page, "^";
348
 
#endif;
349
 
];
350
 
 
351
 
[ AH_Menu ;
352
 
    AH_CalcMenu();
353
 
    if (pretty_flag == 0) AH_num_pages = 1;
354
 
    AH_current_page = 1;
355
 
    DoMenu(#r$AH_HintPrint, #r$AH_HintInfo, #r$AH_HintMenu);
356
 
];
357
 
 
358
 
! Okay, the way the HintSub works is like so:
359
 
!   Check to make certain a hint is available and not yet solved.
360
 
!     If not, exit with a comment to that effect.
361
 
!   Find out how many puzzles are currently available and not already given
362
 
!     If none are left, comment that no new hints are available, and past
363
 
!       hints can be viewed using the REVIEW command.
364
 
!   If more than one puzzle is available at this point, pass it off to a 
365
 
!     menu routine.
366
 
!   Otherwise, do the normal hint for the only available puzzle.
367
 
 
368
 
[ HintSub i j numpuz some_given;
369
 
 
370
 
    AH_UpdateHints();
371
 
 
372
 
#ifdef HINTDEBUG;
373
 
    print "Hints available:^";
374
 
    objectloop (i in Hints) {
375
 
        if (i has general) {
376
 
            print (name) i, "^";
377
 
        }
378
 
    }
379
 
    print "^";
380
 
#endif;
381
 
 
382
 
    numpuz = 0;
383
 
    some_given = 0;
384
 
    objectloop (i in Hints) {         ! j = the first puzzle coming out 
385
 
        if (i has general) {          ! of this loop
386
 
#ifdef GIVEHINTSONCE;
387
 
            if (i hasnt given) {
388
 
                if (numpuz == 0) j = i;
389
 
                numpuz++;
390
 
            } else some_given++;
391
 
        }
392
 
#ifnot;
393
 
            if (numpuz == 0) j = i;
394
 
            numpuz++;
395
 
        }
396
 
        if (i has given || i has solved) some_given++;
397
 
#endif;
398
 
    }
399
 
 
400
 
    if (numpuz==0) {
401
 
        if (some_given ~= 0) {
402
 
            "No new hints are waiting.  Try using REVIEW to look at the hints \
403
 
            you have already seen.";
404
 
        }
405
 
        "You haven't found a puzzle yet to have a hint available!";
406
 
    }
407
 
 
408
 
    if (numpuz > 1) {
409
 
        objectloop (i in Hints) {
410
 
            if (i has general) {
411
 
#ifdef GIVEHINTSONCE;
412
 
               if (i hasnt given) {
413
 
#endif;
414
 
#ifdef HINTDEBUG;
415
 
                    print "Giving in_menu to puzzle: ", (name) i, "^";
416
 
#endif;
417
 
                    give i in_menu;
418
 
#ifdef GIVEHINTSONCE;
419
 
                }
420
 
#endif;
421
 
            }
422
 
        }
423
 
        AH_Menu();
424
 
        objectloop (i in Hints) {
425
 
            if (i has in_menu) {
426
 
#ifdef HINTDEBUG;
427
 
                print "Removing in_menu from puzzle: ", (name) i, "^";
428
 
#endif;
429
 
                give i ~in_menu;
430
 
            }
431
 
        }
432
 
        rtrue;
433
 
    }
434
 
 
435
 
    AH_ShowHints(j);
436
 
 
437
 
];
438
 
 
439
 
[ ReviewSub i count;
440
 
 
441
 
    AH_UpdateHints();
442
 
 
443
 
    count = 0;
444
 
 
445
 
    objectloop (i in Hints) {
446
 
#ifdef REVIEWGIVENONLY;
447
 
        if (i has given) {
448
 
#ifnot;
449
 
        if (i has solved || i has given) {
450
 
#endif;
451
 
#ifdef HINTDEBUG;
452
 
            print "Adding puzzle: ", (name) i, "^";
453
 
#endif;
454
 
            give i in_menu;
455
 
            count++;
456
 
        }
457
 
    }
458
 
 
459
 
    if (count == 0)
460
 
        "No hints are available to be reviewed.";
461
 
 
462
 
    AH_Menu();
463
 
 
464
 
    objectloop (i in Hints) {
465
 
        if (i has in_menu) {
466
 
#ifdef HINTDEBUG;
467
 
            print "Removing in_menu from ", (name) i, "^";
468
 
#endif;
469
 
            give i ~in_menu;
470
 
        }
471
 
    }
472
 
 
473
 
    rtrue;
474
 
];
475
 
 
476
 
! Disabling the hints system
477
 
[ HintsOffSub;
478
 
    if (AH_hints_available == 0) 
479
 
        "Hints are already disabled.";
480
 
    AH_hints_available = 0;
481
 
    "Hints are now disabled.";
482
 
];
483
 
 
484
 
[ HintsOnSub;
485
 
    if (AH_hints_available == 1)
486
 
        "Hints are already on!";
487
 
    "Hints cannot be re-enabled after being disabled.";
488
 
];
489
 
 
490
 
! And now we declare the grammar for HINT and REVIEW
491
 
 
492
 
#ifdef HINTDEBUGVERBS;
493
 
Verb "puzzles" "allpuzzles"
494
 
        *                                              -> AllPuzzlesSub;
495
 
 
496
 
Verb "allhints"
497
 
        *                                              -> AllHintsSub;
498
 
 
499
 
#endif;
500
 
 
501
 
Verb "hints"
502
 
        * "on"                                         -> HintsOnSub
503
 
        * "off"                                        -> HintsOffSub
504
 
        *                                              -> HintSub;
505
 
 
506
 
Verb "hint"
507
 
        *                                              -> HintSub;
508
 
 
509
 
#ifndef NOHINTREVIEW;
510
 
Verb "review"
511
 
        *                                              -> ReviewSub;
512
 
#endif;
513