!       Hints           An Inform 6 library by L. Ross Raszewski
!   Version 2           To produce nicely formatted hints.
!                       Upgraded and made easier to use
!
! REQUIRES DoMenu.H, Center.H, and AltMenu.H
!
!   New in this version: The hint may now be in the short_name rather than the
!      descriptionof the hint.  I don't know what I was thinking.
!   Multilingual support.
!   The hints left descriptor has been moved to the function HintIdent, which
!        you may replace if you so desire.  Hintident is called with three
!               arguments, x - set to 1 before the hint is printed, 2 after.
!                          i - the number of hints left
!                          j - the total number of hints
!
!   The hint_menu no longer needs to be called hint_menu.  in fact, it can't,
!       unless it's defined before inclusion. Instead, set the global hint_menu
!       equal to your hint menu.
!  Predefine Helpsub to change its message.
! define NO_GRAMMAR to prevent the grammar from being included.
!
! Upon reflection, the older version of this library was clumsy and inflexible
! This system is well suited to adaptive hints and other wonderful things.
! Grammar -
! The verb "Hint" ("Help") calls up the hint menu, which should begin with an
! AltMenu Menu object called hint_menu.  (The first time, you are given the
! option to disable the hints.)
! The children of hint_menu should be the top level hints or categories, and
! so on etc until you reach the actual hints.  The hint categories are
! objects of the class "HintTopic", whose short names are the names of the
! hints.  The children of a HintTopic are of class Hint.  Their descriptions
! contain the actual hints, which are displayed in order.
! Example hierarchy (This is NOT code, it's more a sort of tree):
!       Menu hint_menu
!           Menu "Prologue"
!               HintTopic "What do I do here?"
!                       Hint with desc. "Look around."
!                       Hint w/d "Move around."
!           Menu "Part 1"
!               HintTopic "Who am I?"
!                       Hint w/d "You are Perry Simm"
!               HintTopic "What Do I do?"
!                       Hint w/d "Not a lot"
!                       Hint w/d "Nothing at all"
!                       Hint w/d "because this ain't a real game"
!
! The player sees the menu titled whatever you choose to call the hint_menu,
! on which an option is Prologue.  Under prologue is the option
! "What do I do here?"  Selecting that will display "Look Around".  If the
! player asks for another hint, he gets it.  if not, revealed hints are
! re-reveled when he reenters the menu.  That is, if the player had read
! the first two hints under "What do I do", then went back to the game, he
! could at any time go back to the hint menu, navigate to "What do I do"
! and would automatically have the first two hints displayed.
! HINT_STYLE must be defined before inclusion (or else it defaults to 0)
!  if it's 0, then the hint is displayed thus:
!       Not a lot (2 left)
!  if it's 1, you get:
!       Not a lot [1/4]
!  if it's 2, you get:
!     [3 hints left]-> Not a lot
!     [2 hints left]->
! (Note that when it's 2, you don't get the first hint when you first
! enter a topic; you get [x hints left]-> )
!
! You can move the hintTopics about, or even do wretched things to
! their children. (I wouldn't, but you can)  In an adaptive hint system,
! you could nove the appropriate HintTopic (with its children already inside)
! into the hint_menu when you want the hint available.
!
! The title_bar property of a HintTopic specifies the top line of the hint
! status line.  It defaults to "InvisiHints"  I've included WaitForKey();
! in case you don't have it already.
!
! Questions, comments, rude suggestions?  I'm at [email protected]
System_file;
#ifndef hint_menu;
global hint_menu;
#endif;
#IFNDEF LASTH__TX;
Constant LASTH__TX = "^^^[That's All Folks!]^";
#ENDIF;
#IFNDEF HINTD__TX;
Constant HINTD__TX = "HINTS disabled.";
#ENDIF;
#IFNDEF WaitForKey;
[ WaitForKey str i;
if (str==0) str="(Please Press Any Key)";
print (string) str;
@read_char 1 0 0 i;
];
#EndIf;

[ HintIdent x i j;
               switch(x){
                       1: if (HINT_STYLE==2) {
                               print "[",i, " hint";
                               if (i>1) print "s";
                               print " left]-> ";
                               return 1;}
                       2: if (HINT_STYLE==1) {
                               j=children(self)-i;
                               print " [",j,"/",j+i,"]";
                               };
                          if (HINT_STYLE==0) {
                               print " (", i, " hint";
                               if (i>1) print "s";
                               print " left.)";
                               }
                               }
return 0;
];

#IFNDEF Helpsub;
[ HelpSub;
       if (hint_menu hasnt general)
       {print "[Warning: It is recognized that the temptation for help \
       may at times be so exceedingly strong that you might fetch hints \
       prematurely. Therefore, you may at any time during the story type \
       HINTS OFF, and this will disallow the seeking out of help for the \
       present session of the story. If you still want a hint now, indicate \
       HINT.]"; give hint_menu general;
        rtrue;}
       if (hint_menu has locked)
               print_ret "Hints have been disabled.";
hint_menu.select();
];
#ENDIF;
[ HelpOffSub;
       print (string) HINTD__TX;
       give hint_menu locked;
       rtrue;
       ];
#ifndef HINT_STYLE;
Constant HINT_STYLE 0;
#ENDIF;
Class HintTopic
       class Option,
       with    printsn [; print (name) self;],
               number 0,
               title_bar "InvisiHints",
               select [ o i j;
                        if (pretty_flag==0) {
                               self.title_bar();
                               self.printsn();
                               print "^Press ENTER for another hint, Q to
                                       return to the menu.";
                               jump disph;
                               }
                        @erase_window -1;
                        @split_window 3;
                        @set_window 1;
                        i=0->33; if (i==0) i=80;
                        @set_cursor 1 1;
                        style reverse;
                        spaces(i);
                        CenterU(self.title_bar,1);
                        @set_cursor 2 1; spaces (i);
                        style bold;
                        CenterU(self.printsn,2);
               style roman; style reverse;
               @set_cursor 3 1; spaces(i);
               @set_cursor 3 2; print "RETURN = read hint";
               j=i-17; @set_cursor 3 j;
               print "Q = previous menu";
               style roman; font off;
               @set_window 0;
               .disph;
               print "^^^^^";
               i=0;
               objectloop (o in self) {
                       if (o has general) { o.GiveHint(); new_line; i++;}
                       }
               i=children(self)-i;
               if (i==0) { WaitForKey(LASTH__TX); return 2;}
               for (o=child(self):o has general:o=sibling(o));
               do {
               if (HintIdent(1,i,j)==1) {

               do { @read_char 1 0 0 j; } until (j == 'Q' or 'q' or 27
                                                or 10 or 13 or 132);
               if (j== 'Q' or 'q' or 27) return 2;
               if (j== 10 or 13 or 132) o.GiveHint();
               i--;
               jump loopover;
               }
               o.GiveHint();
               i--;
               if (i==0) jump loopover;
               HintIdent(2,i,j);
               do { @read_char 1 0 0 j; } until (j == 'Q' or 'q' or 27
                                                or 10 or 13 or 132);
               if (j== 'Q' or 'q' or 27) { give o ~general; return 2;}
               .loopover;
               o=sibling(o);
               new_line;
               } until (i==0);
               WaitForKey(LASTH__TX); return 2;
               ];
Class Hint
       with GiveHint [;
                       if (self provides description)
                               PrintOrRun(self,description,1);
                         else print (name) self;
                        give self general;];


#IFNDEF NO_GRAMMAR;
Verb meta "Help" "Hint" "hints" "clues"  "clue"
                               * "off"                         ->HelpOff
                               *                               ->Help;
#ENDIF;