Form DEMO_COPYCAT_FORM /* /* © Copyright 2005 Hewlett-Packard Development Company, L.P. /* /* Consistent with FAR 12.211 and 12.212, Commercial Computer Software, /* Computer Software Documentation, and Technical Data for Commercial /* Items are licensed to the U.S. Government under vendor's standard /* commercial license. /* /*/ /* /************************************************************************ /* /* This somewhat whimsical form demonstrates how you can do some /* very unusual things in IFDL, without any program involvement. /* /* --- See the next page for notes on color terminals --- /* /* This form shows examples of: /* /* A COLOR & MONOCHROME APPLICATION /* This form shows how to do an application that can be run on a /* black & white screen OR on a color screen by using the FOR /* clause in Attributes to get different effects. /* /* SPECIAL IFDL FUNCTION DEFINITIONS /* It shows an example of the "Builtin Function", "User Function", /* and the "Undefined Function" responses. /* /* POSITION STEPS /* It shows how a POSITION step can take you to a field/icon, /* but that you can go from there to another field/icon without /* doing any input. This happens because a POSITION step in the /* field/icon ENTRY RESPONSE re-positions you before you actually /* do any input. /* /* HIGHLIGHT WHENS /* It shows how HIGHLIGHT WHENS are applied immediately, as soon as /* the when condition changes. (This is how the flashing is done.) /* /* CONCEALED WHENS /* It shows how some fields and text can be concealed, or displayed. /* /* INCREMENTING AN ARRAY INDEX /* It shows a method for getting around the "no arithmetic" restriction /* in IFDL, when you need to access the *next* element in an array. /* (Essentially a LET X = X + 1 operation) /* /* RESPONSE STEP EXECUTION ORDER /* By running this form with tracing turned on, you can get a good /* feel for which response steps are executed immediately (Like LET, /* DISPLAY, REMOVE...) and which steps cause some later action /* (like POSITION...). In addition you'll see how POSITION can in /* turn cause other sets of response steps to be executed. /* /*********************************************************************/ /* /* 7-Feb-89 DEC Original /* /*********************************************************************/ /*********************************************************************/ /* /* ------------------- NOTE about VT340 Terminals --------------------- /* | | /* | If you have a VT340, press the SETUP key and see what version | /* | of the firmware is (look in the upper right hand corner). | /* | | /* | V2.0 or earlier: | /* | These older terminals will display the highlighted | /* | text in reverse video. That's the only option. | /* | | /* | V2.1 or newer: | /* | These newer terminals will act like the older VT340's | /* | if the color-map setting is set to 'color-1' mode. | /* | | /* | If you set the color-map setting to 'color-2' mode, then | /* | the highlighted text will still come out in reverse video, | /* | but it will use a light blue (CYAN) instead of yellow | /* | | /* | To see or change the color-map setting, press the SET-UP key,| /* | select "Global Set-Up" and change the "Color Map" setting | /* | to "color-2" | /* | | /* | It is possible to upgrade older VT340's to the newer firmware. | /* | This lets you use the REVERSE highlight as a separate color, | /* | instead of simply reversing the background/foreground colors | /* | as it does for monochrome and older VT340's. | /* | | /* | This demo has been carefully designed to work on either type | /* | of VT340. But in general, applications will want to use all 4 | /* | colors that are available in the VT241 and the newer VT340's. | /* | | /* -------------------------------------------------------------------- /* /* ------------------- NOTE about VT241 Terminals --------------------- /* | | /* | VT241 terminals can be setup to handle "Mono + Color Display" | /* | or just "Color Display". You should have it set to the | /* | "Mono + Color Display" setting. To do this, press the SET-UP | /* | key (F3), press ENTER to select the "Display" Choice. Over on | /* | the right hand side is the menu choice that will read one of: | /* | "Monochrome Display", "Mono + Color Display", or "Color Display"| /* | If you see the text changing colors instead of the boxes, the | /* | is on the wrong setting. | /* | | /* | VT240 terminals that have a monochrome monitor should be set | /* | to Monochrome. | /* | | /* -------------------------------------------------------------------- /* /* ------------------- NOTE about OTHER Terminals --------------------- /* | | /* | Other color terminals may or may not work as expected. | /* | If they do not emulate a VT241 or VT340 exactly, then you | /* | will see unusual colors. | /* | | /* | However, since DECforms looks at the REGIS characteristic, | /* | you can make this form work on any color terminal by | /* | first setting the terminal to NOREGIS. In this case, DECforms | /* | will think the terminal is monochrome, and the normal | /* | Bold/Reverse settings will be used. | /* | | /* -------------------------------------------------------------------- /* /************************************************************************/ Form Data /* /* Variables that control the display/input of the sequence /*/ X Unsigned Byte Value 1 /* Position in sequence */ MAX_X Unsigned Byte Value 2 /* Length of sequence */ MAX_MAX Unsigned Byte Value 20 /* # of OCCURS in BOX */ /* /* This array contains key info to making this work. /*/ Group BOX /* Array to control the Sequence */ Occurs 20 NEXT_X Unsigned Byte /* Used to do X = X + 1 */ IS_A Character(1) /* Contains the actual sequence */ RANDOM_X Character(1) /* Contains "random" sequence */ End Group /* /* Miscellaneous variables, constants /*/ HIGH_SCORE Unsigned Byte Value 0 /* High score, this session */ SCORE_VISIBLE Unsigned Byte Value 0 /* True=Show the scores */ FLASH_DELAY Unsigned Byte Value 0 /* Parameter to FLASH_BOX */ FLASH_NOW Character(1) /* Code to control FLASHING */ RESTART_Q Character(54) Value " Press RETURN to play, press HELP for instructions" RESTART_Q_HI Unsigned Byte Value 0 /* Highlight control for RESTART_Q */ RANDOM_SPOT Unsigned Byte Value 1 /* Random 'seed' */ TRUE Unsigned Byte Value 1 /* For readability */ FALSE Unsigned Byte Value 0 /* For readability */ LIB_CVT_OPERATION Unsigned Longword Value 19 /* LIB$K_SECOND_OF_MINUTE */ LIB_CVT_TIME_SECONDS Unsigned Longword FFLOAT_VALUE Ffloating /* /* We define text constants so that the help text is defined /* in one place (but referenced in lots of places.) /* This is done to make maintenance of this form easier. /*/ HELP_MSG Character(80) Value " (Press the Help key for instructions)" NO_MORE_HELP_MSG Character(80) Value " (No more help available)" /* /* Variables that control how long the wait (delays) are /*/ WAIT_SIZE Unsigned Byte Value 1 /* Relative wait times */ WAIT_NORMAL Unsigned Byte Value 1 /* For readability */ WAIT_LESS Unsigned Byte Value 2 /* For readability */ WAIT_MORE Unsigned Byte Value 3 /* For readability */ End Data Layout COPY_CAT /* /* This is the layout section -- it handles both color and monochrome /* terminals. It contains all the device specific information for /* the application. /*/ /* /* For Monochrome applications, as well as many Color applications, /* the "Device" clause would merely contain "Type %VT100" -- and it /* would support all DEC terminals. /* /* In this case, we are doing some fancy things with the colors, /* so we want to be able to distinguish between color and monochome /* terminals (the FOR clause in Attributes, below). /*/ Device Terminal COLOR_VT Type %VT200 COLOR {VT200 Color or newer} Terminal MONO_VT Type %VT100 {VT100 B/W or newer} End Device Size 24 Lines by 80 Columns /* /* Define all the keys we need /*/ Function SELECT_A Is %UP %KP_8 End Function Function SELECT_B Is %LEFT %KP_4 End Function Function SELECT_C Is %RIGHT %KP_6 End Function Function SELECT_D Is %DOWN %KP_2 End Function Function QUIT Is %F10 %CONTROL_Z End Function Function REPAINT Is %CONTROL_W %CONTROL_R End Function Function RETURN_KEY Is %CARRIAGE_RETURN %KP_ENTER End Function Function WAIT_KEY Is %PF4 End Function Function SHOW_SCORE Is %PF3 End Function /* /* Define named attributes for the 4 boxes and text fields /* ------------------------------------------------------- /* /* For Monochrome terminals, we want to use this scheme: /* - Highlight some text with BOLD /* - Highlight some text with REVERSE /* - Highlight the boxes with BOLD+REVERSE (shows up the best) /* /* For Color terminals, we want to use this scheme (3 or 4 colors max) /* - Background is Black /* - "Normal" Text is Yellow /* - "Highlight" text with light Blue (CYAN) /* - Reserve the 4th color for each box as we display it /* so they can be unique colors. /* /* How do colors work? You assign colors to the 4 possible text /* attributes: /* - Background color /* - Foreground color (This color is used for REVERSE of a SPACE on /* old VT340's) /* - Bold color ("Normal" Text) (All text uses BOLD) /* - Reverse color (This color is used when REVERSE is specified /* on VT241 & Newer VT340's) /* /* NOTE: We'd normally use the FOREGROUND color for "normal" text. /* In this particular application, however, we are displaying color /* patches by using the SPACE character in special colors. /* So, for this application only, we are using the BOLD attribute /* to control the color used for all "normal" text. This is different /* from the way you'd probably use the color attributes. /* /* NOTE: When we display the help panel, we are not doing the flashing, /* so we have an additional color available. To use this, we define /* the attribute HELP_TITLE_TEXT. This attribute lets us put the /* Help Panel title up in color, if possible (it's not possible on /* older VT340's.) /* /* Below, we create the appropriate attribute /* combinations for each type of highlighting function we need for /* each kind of terminal (Color or Monochrome) /*/ Attribute BOX_ATTR_NORMAL {Invisible BOX (SPACE character)} For MONO_VT Is NOBOLD NOREVERSE For COLOR_VT Is NOBOLD NOREVERSE End Attribute Attribute BOX_ATTR_FLASH {Flash of SPACE character} For MONO_VT Is BOLD REVERSE {Brightest for Monochrome} For COLOR_VT Is REVERSE {Use the color mapped to REVERSE } { (VT241, new VT340) } {Use the color mapped to FOREGROUND} End Attribute { (old VT340) } Attribute BOLD_TEXT For MONO_VT Is BOLD {Bolded Text on Monochrome} For COLOR_VT Is BOLD {Use the color mapped to BOLD} End Attribute Attribute REVERSE_TEXT For MONO_VT Is REVERSE {Reversed Text on Monochrome} For COLOR_VT Is BOLD {Use the color mapped to BOLD} End Attribute {-since REVERSE is used for flashing} Attribute NORMAL_TEXT For MONO_VT Is NOBOLD NOREVERSE For COLOR_VT Is BOLD {Use the color mapped to BOLD} End Attribute {-since FOREGROUND is used for flashing} Attribute HELP_TITLE_TEXT For MONO_VT Is BOLD {Bolded Text on Monochrome} For COLOR_VT Is REVERSE {Use the color mapped to REVERSE } { (VT241, new VT340) } {Use REVERSE VIDEO (Backg/Foreg) } End Attribute { (old VT340) } /* /* These are the viewports. If we were only doing a MONOCHROME version /* we wouldn't need any of these, because the default viewport would be /* sufficient. /* /* The reason we use lots of viewports is to get around the /* 4-colors-at-a-time restriction. By putting each of the Boxes /* in their own viewports, we can tinker with the colors, and get /* each box to have it's own unique color. We never have more /* than 4 colors on the screen at any one time (a terminal hardware /* restriction), but we use more than 4 colors in the application /* since we use several viewports. /* /* Notice that all the viewports specify the exact same colors /* for the BACKGROUND and the BOLD attributes -- these are used /* by the text on the screen that's always visible. /* The FOREGROUND and the REVERSE attributes are always the same, /* and change from vieweport to viewport -- these are used to /* Flash the boxes. /*/ Viewport VP_MAIN { Main game board } Lines 1 thru 23 Columns 1 thru 80 Display Viewport Background Color BLACK Foreground Color CYAN Reverse Foreground Color CYAN Bold Foreground Color YELLOW End Viewport Viewport VP_A { For BOX A } Lines 6 thru 8 Columns 32 thru 38 Display Viewport Background Color BLACK Foreground Color RED Reverse Foreground Color RED Bold Foreground Color YELLOW End Viewport Viewport VP_B { For BOX B } Lines 12 thru 14 Columns 19 thru 25 Display Viewport Background Color BLACK Foreground Color GREEN Reverse Foreground Color GREEN Bold Foreground Color YELLOW End Viewport Viewport VP_C { For BOX C } Lines 12 thru 14 Columns 45 thru 51 Display Viewport Background Color BLACK Foreground Color CYAN Reverse Foreground Color CYAN Bold Foreground Color YELLOW End Viewport Viewport VP_D { For BOX D } Lines 18 thru 20 Columns 32 thru 38 Display Viewport Background Color BLACK Foreground Color MAGENTA Reverse Foreground Color MAGENTA Bold Foreground Color YELLOW End Viewport /********************************************************************* /* /* These are the responses (ifdl subroutines) that do nearly all the /* work. The form logic has basically two states: /* /* 1) Show the user the current sequence. This is done by using /* POSITION steps in the ENTRY responses for the 4 boxes. /* The ENTRY responses 'flash' the box, and then position to /* the next box in the sequence. /* /* 2) User input. In this state, we keep track of what point /* in the sequence the user is at. Entering the next key /* stroke successfully 'flashes' the box, and then waits for /* the next keystroke. /* /*********************************************************************/ /* /* What to do when the user guesses the next box in the sequence correctly /*/ Internal Response USER_GOT_BOX /* /* Clear message area /*/ Message " " /* /* Flash the box /*/ Let FLASH_DELAY = FALSE Include FLASH_BOX /* /* Count this keystroke (so we look for the next box /* in the sequence) /*/ If X < MAX_X Then /* /* Add one, since user isn't at end of sequence /*/ Let X = BOX(X).NEXT_X { Let X=X+1 } Position Immediate To Icon WAIT_SPOT On MAIN_PANEL Message " -- Enter Next Keystroke --" Else /* /* User made it to the end of sequence, so make it longer /*/ Include EXTEND_SEQUENCE End If End Response /* /* User missed... (start over) /*/ Internal Response USER_MISSED_BOX Signal Message " ---- Start Over ----" /* /* Set high score /*/ If MAX_X > HIGH_SCORE Then Let HIGH_SCORE = MAX_X End If /* /* Start over /*/ Include RESTART End Response /* /* The way we "randomize" things is we reload the array from /* a canned sequence array. To make it look random, we re-load /* from a different starting location in the array each time. /* The internal response below (RESET_SEQUENCE) does the loading, /* and this internal response (NEXT_RANDOM_SPOT) wraps the index /* from the end, back to the first spot in the array. /*/ Internal Response NEXT_RANDOM_SPOT Let RANDOM_SPOT = BOX(RANDOM_SPOT).NEXT_X { Let R.S.=R.S.+1 } If RANDOM_SPOT > MAX_MAX Then Let RANDOM_SPOT = 1 End If End Response /* /* Get new random sequence /*/ Internal Response RESET_SEQUENCE Include NEXT_RANDOM_SPOT Let BOX(1).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(2).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(3).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(4).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(5).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(6).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(7).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(8).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(9).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(10).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(11).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(12).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(13).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(14).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(15).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(16).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(17).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(18).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(19).IS_A = BOX(RANDOM_SPOT).RANDOM_X Include NEXT_RANDOM_SPOT Let BOX(20).IS_A = BOX(RANDOM_SPOT).RANDOM_X End Response /* /* Call to get the time-of-day in seconds /* as a random number /*/ Internal Response RANDOM_START Call "LIB$CVT_FROM_INTERNAL_TIME" Using LIB_CVT_OPERATION LIB_CVT_TIME_SECONDS If LIB_CVT_TIME_SECONDS > 0 And LIB_CVT_TIME_SECONDS <= MAX_MAX Then Let RANDOM_SPOT = LIB_CVT_TIME_SECONDS Else If LIB_CVT_TIME_SECONDS < 30 Then Let RANDOM_SPOT = 5 Else If LIB_CVT_TIME_SECONDS < 40 Then Let RANDOM_SPOT = 10 Else If LIB_CVT_TIME_SECONDS < 50 Then Let RANDOM_SPOT = 15 Else Let RANDOM_SPOT = 19 End If End If End If End If End Response /* /* Ask the user if it's ok to start over again /*/ Internal Response RESTART /* /* Just to make things interesting... /*/ Include RANDOM_START /* /* Ask user if we should restart /*/ Let RESTART_Q_HI = TRUE Position Immediate To Field RESTART_Q On MAIN_PANEL End Response /* /* Reset & start over /*/ Internal Response RESET_ALL /* /* Set length of sequence back to minimum /*/ Let MAX_X = 2 /* /* Reset to a new sequence /*/ Include RESET_SEQUENCE Include SHOW_SEQUENCE End Response /* /* User Quit, time to go home /*/ Internal Response QUIT_ALL /* /* Return to DCL (Or other Application) /*/ Remove All Return End Response /* /* Add one more 'flash' to the sequence /*/ Internal Response EXTEND_SEQUENCE /* /* If we can, extend the sequence by one more /*/ If MAX_X < MAX_MAX Then Message " -- Adding another --" Let MAX_X = BOX(MAX_X).NEXT_X { Let MAX_X=MAX_X+1 } Include SHOW_SEQUENCE Include NEXT_RANDOM_SPOT /* Randomize... */ /* /* Else, user made it to the end /*/ Else Signal %REVERSE Message " You made it thru the works!" Let RANDOM_SPOT = 10 /* No one will make it thru 3 times! */ Include RESTART End If End Response /* /* This changes the wait intervals /*/ Internal Response WAIT_CHANGE If WAIT_SIZE = WAIT_NORMAL Then Let WAIT_SIZE = WAIT_MORE Message " (Wait time increased. Press PF4 again to make it less.)" Else If WAIT_SIZE = WAIT_MORE Then Let WAIT_SIZE = WAIT_LESS Message " (Wait time decreased. Press PF4 again to make it average.)" Else If WAIT_SIZE = WAIT_LESS Then Let WAIT_SIZE = WAIT_NORMAL Message " (Wait time back to normal. Press PF4 again to make it more.)" End If End If End If End Response /* /* Change the display of the scores (on/off) /*/ Internal Response TOGGLE_SCORE_DISPLAY If SCORE_VISIBLE = TRUE Then Let SCORE_VISIBLE = FALSE Else Let SCORE_VISIBLE = TRUE End If End Response /* /* Functions /*/ /* /* Since we've explicitly defined all the keys we want to use, /* the "Builtin Function" makes any keys defined by DEFforms /* defaults print our message. /*/ Function Response Builtin Function Message HELP_MSG End Response /* /* For consistency (to the user) we want the same message to come /* out for any keys that are completely undefined (by this IFDL file /* or by DECforms). /*/ Function Response Undefined Function Message HELP_MSG End Response /* /* This is the same as the built-in response for NEXT HELP -- almost. /* In this application, we want to reset things after you /* return from help. (Also, the messages are slightly changed /* to be more appropriate to this application). /*/ Function Response NEXT HELP {1} If Help Message Available Then /* Help message available */ Message Help /* ....print it */ {2} Else If Help Panel Exists Then /* Help Panel available, */ Enter Help /* ....use it */ /* /* --- Addition to the regular help key function --- /* /* After reading help, restart the sequence to avoid confusion. /* (The ENTER HELP step is like a subroutine call. Thus, /* we put the restart here instead of in the exit response /* for the help panel.) /*/ Include RESTART {3} Else If Help Active Then /* Help already in use */ Message NO_MORE_HELP_MSG Position To Current Item /* Re-enable Help Msg */ {4} Else If Help Message Exists Then /* ....no more, though */ Message NO_MORE_HELP_MSG Position To Current Item /* Re-enable Help Msg */ {5} Else /* No help at all */ Message NO_MORE_HELP_MSG End If End If End If End If End Response /* /* This is how you refresh the screen /*/ Function Response REPAINT Refresh All End Response /* /* This changes the wait intervals /*/ Function Response WAIT_KEY Include WAIT_CHANGE End Response /* /* This is the response for the QUIT key /*/ Function Response QUIT Include QUIT_ALL End Response /* /* This toggles the display of the scores /*/ Function Response SHOW_SCORE Include TOGGLE_SCORE_DISPLAY End Response /* /* These next 4 functions handle the user's keystrokes. There is /* one for each of the four boxes. Each checks to see if the /* proper key was pressed, and then calls the appropriate /* internal response. /*/ Function Response SELECT_A If BOX(X).IS_A = "A" Then Include USER_GOT_BOX Else Include USER_MISSED_BOX End If End Response Function Response SELECT_B If BOX(X).IS_A = "B" Then Include USER_GOT_BOX Else Include USER_MISSED_BOX End If End Response Function Response SELECT_C If BOX(X).IS_A = "C" Then Include USER_GOT_BOX Else Include USER_MISSED_BOX End If End Response Function Response SELECT_D If BOX(X).IS_A = "D" Then Include USER_GOT_BOX Else Include USER_MISSED_BOX End If End Response /* /* The Enable Response gets everything going. It needs to initialize /* all the variables (mainly the arrays). It also does the initial /* position to the question "Press Return to start..." /*/ Enable Response /* /* Put the screen up /*/ Display MAIN_PANEL /* /* Initialize variables /*/ Let FLASH_NOW = " " /* Set to A,B,C,D to flash the box */ Let BOX(1).NEXT_X = 2 /* Store +1 for each element */ Let BOX(2).NEXT_X = 3 Let BOX(3).NEXT_X = 4 Let BOX(4).NEXT_X = 5 Let BOX(5).NEXT_X = 6 Let BOX(6).NEXT_X = 7 Let BOX(7).NEXT_X = 8 Let BOX(8).NEXT_X = 9 Let BOX(9).NEXT_X = 10 Let BOX(10).NEXT_X = 11 Let BOX(11).NEXT_X = 12 Let BOX(12).NEXT_X = 13 Let BOX(13).NEXT_X = 14 Let BOX(14).NEXT_X = 15 Let BOX(15).NEXT_X = 16 Let BOX(16).NEXT_X = 17 Let BOX(17).NEXT_X = 18 Let BOX(18).NEXT_X = 19 Let BOX(19).NEXT_X = 20 Let BOX(20).NEXT_X = 21 Let BOX(1).RANDOM_X = "B" Let BOX(2).RANDOM_X = "C" Let BOX(3).RANDOM_X = "A" Let BOX(4).RANDOM_X = "C" Let BOX(5).RANDOM_X = "D" Let BOX(6).RANDOM_X = "B" Let BOX(7).RANDOM_X = "A" Let BOX(8).RANDOM_X = "D" Let BOX(9).RANDOM_X = "B" Let BOX(10).RANDOM_X ="C" Let BOX(11).RANDOM_X ="D" Let BOX(12).RANDOM_X ="B" Let BOX(13).RANDOM_X ="A" Let BOX(14).RANDOM_X ="D" Let BOX(15).RANDOM_X ="C" Let BOX(16).RANDOM_X ="D" Let BOX(17).RANDOM_X ="B" Let BOX(18).RANDOM_X ="A" Let BOX(19).RANDOM_X ="D" Let BOX(20).RANDOM_X ="A" /* /* This puts all the boxes and user fields on the activation list /*/ Activate Panel MAIN_PANEL Activate Panel PANEL_A Activate Panel PANEL_B Activate Panel PANEL_C Activate Panel PANEL_D /* /* Initialize our random starting point /*/ Include RANDOM_START /* /* This response loads the initial random values, and positions /* to the "Press return to start..." question /*/ Include RESTART End Response /* /* To keep things from flashing by too fast, we need to put some /* time delays in. We do this by printing the dot pattern in /* the message area. /* /* We have 3 sizes of delays. /*/ Internal Response WASTE_TIME_SMALL Message " ." Message " " End Response Internal Response WASTE_TIME_MEDIUM Message " ." Message " ..." Message " ....." Message " ..." Message " ." Message " " End Response Internal Response WASTE_TIME_LARGE Message " ." Message " ..." Message " ....." Message " ......." Message " ........." Message " ..........." Message " ............." Message " ..............." Message " ................." Message " ..................." Message " ....................." Message " ......................." Message " ........................." Message " ..........................." Message " ........................." Message " ......................." Message " ....................." Message " ..................." Message " ................." Message " ..............." Message " ............." Message " ..........." Message " ........." Message " ....." Message " ..." Message " ." Message " " End Response /* /* This controls how much time we wait at the beginning of the game /*/ Internal Response WAIT_TIME_RESET If WAIT_SIZE = WAIT_NORMAL Then Include WASTE_TIME_LARGE Else If WAIT_SIZE = WAIT_MORE Then Include WASTE_TIME_LARGE Else If WAIT_SIZE = WAIT_LESS Then Include WASTE_TIME_MEDIUM End If End If End If End Response /* /* This controls the time delay during the display of the sequence /*/ Internal Response WAIT_TIME_FLASH If WAIT_SIZE = WAIT_NORMAL Then Include WASTE_TIME_MEDIUM Else If WAIT_SIZE = WAIT_MORE Then Include WASTE_TIME_LARGE Else If WAIT_SIZE = WAIT_LESS Then Include WASTE_TIME_SMALL End If End If End If End Response /* /* This controls the time delay of a flash during a keypress /*/ Internal Response WAIT_TIME_INPUT If WAIT_SIZE = WAIT_MORE Then Include WASTE_TIME_MEDIUM End If End Response /* /* Start things so we Show the Sequence to the user /*/ Internal Response SHOW_SEQUENCE /* /* X is the position we're currently showing /*/ Let X = 1 /* /* Go to the first BOX /* (Which will FLASH it) /*/ Include POSITION_TO_BOX /* /* Pause, before we start the FLASHing /*/ Include WAIT_TIME_RESET End Response /* /* FLASH the current box we're at /* /* We need the DISPLAY & REMOVE steps below to force the Box's /* viewport/panel onto the screen. Normally, we wouldn't need /* this. However, we are positioning to the boxes, but never /* doing input from them. The Form Manager would therefore /* optimize, and never put them on the screen since we never /* actually did input from them. In our case, since we're trying /* to 'flash' them on the screen, we need to explicitly display /* them and remove them. Note that the DISPLAY step specifies /* the panel name, while the REMOVE step specifies the viewport name. /*/ Internal Response FLASH_BOX If BOX(X).IS_A = "A" Then Let FLASH_NOW = "A" Display PANEL_A Else If BOX(X).IS_A = "B" Then Let FLASH_NOW = "B" Display PANEL_B Else If BOX(X).IS_A = "C" Then Let FLASH_NOW = "C" Display PANEL_C Else If BOX(X).IS_A = "D" Then Let FLASH_NOW = "D" Display PANEL_D End If End If End If End If If FLASH_DELAY = TRUE Then /* True means we're showing the seq. */ Include WAIT_TIME_FLASH Else /* False means it's a user keypress */ Include WAIT_TIME_INPUT End If Remove VP_A VP_B VP_C VP_D Let FLASH_NOW = " " /* Turn Flash off */ End Response /* /* Position to the box pointed to by X /*/ Internal Response POSITION_TO_BOX If BOX(X).IS_A = "A" Then Position Immediate To Icon BOX_A On PANEL_A Else If BOX(X).IS_A = "B" Then Position Immediate To Icon BOX_B On PANEL_B Else If BOX(X).IS_A = "C" Then Position Immediate To Icon BOX_C On PANEL_C Else If BOX(X).IS_A = "D" Then Position Immediate To Icon BOX_D On PANEL_D End If End If End If End If End Response /* /* This is what we do when we VISIT each icon /*/ Internal Response BOX_ENTRY_RESPONSE /* /* FLASH this box /*/ Let FLASH_DELAY = TRUE Include FLASH_BOX /* /* If not at end of sequence, go to the next box /*/ If X < MAX_X Then Let X = BOX(X).NEXT_X { Let X=X+1 } Include POSITION_TO_BOX Else /* /* If at end of sequence, go back to User Input /*/ Let X = 1 Position Immediate To Icon WAIT_SPOT On MAIN_PANEL End If End Response Field Default BOX_DEFAULT Entry Response Include BOX_ENTRY_RESPONSE End Response End Default Panel MAIN_PANEL /* /* This is the game board /*/ Viewport VP_MAIN Use Help Panel MAIN_HELP /* /* Title /*/ Literal Text Line 2 Column 21 Value " C O P Y C A T " Display BOLD_TEXT Font Size Double Wide End Literal Literal Text Line 3 Column 26 Value "A DECforms IFDL Demo" Display NORMAL_TEXT End Literal /* /* Put up the box outlines /*/ Literal Rectangle Line 5 Column 30 Line 9 Column 40 Display NORMAL_TEXT End Literal Literal Rectangle Line 11 Column 17 Line 15 Column 27 Display NORMAL_TEXT End Literal Literal Rectangle Line 11 Column 43 Line 15 Column 53 Display NORMAL_TEXT End Literal Literal Rectangle Line 17 Column 30 Line 21 Column 40 Display NORMAL_TEXT End Literal /* /* Put up the extended "X" in the middle /*/ Literal Text Line 12 Column 34 Value "\ /" Display NORMAL_TEXT End Literal Literal Text Line 14 Column 34 Value "/ \" Display NORMAL_TEXT End Literal /* /* Put up the score, if requested /*/ Icon High_Score_Text Protected Concealed When SCORE_VISIBLE = FALSE Literal Text Line 6 Column 6 Value "High Score" Display NORMAL_TEXT End Literal End Icon Field High_Score Next Line Same Column +4 Output Picture 9R9 /* suppress leading zeros */ Protected Concealed When SCORE_VISIBLE = FALSE End Field Icon Score_Text Protected Concealed When SCORE_VISIBLE = FALSE Literal Text Line 6 Column 63 Value "Score" Display NORMAL_TEXT End Literal End Icon Field MAX_X Next Line Same Column +1 Output Picture 9R9 /* suppress leading zeros */ Protected Concealed When SCORE_VISIBLE = FALSE End Field /* /* Place for the cursor to rest (Center of "X") /*/ Icon WAIT_SPOT No Data Input Message HELP_MSG Display NORMAL_TEXT %Keypad_Application Entry Response /* /* X = 1 when we start a new sequence. /* After that, since we are always positioned to WAIT_SPOT, /* we never execute this Entry Response again. /*/ If X = 1 Then Message " -- Enter First Keystroke --" Include NEXT_RANDOM_SPOT /* Randomize... */ End If End Response Literal Text Line 13 Column 35 Value "X" End Literal End Icon /* /* This is the "Press RETURN to start..." "icon". It comes up in /* reverse video when it's active. When not in use, the value of /* the field is set to blank (so it disappears from the screen) /* /* (In future versions, this would likely be an ICON with a /* Concealed When clause, instead of the FIELD with an /* Output When clause that's below. Concealed When clauses /* can cause some extra screen re-painting when they change on-the-fly. /* Concealed Whens are *always* appropriate when the value of the /* When clause stays constant during the display of a panel.) /*/ Field RESTART_Q Line 23 Column 9 No Data Input Message HELP_MSG /* /* When we exit this field, we need to 'turn it off' again /*/ Exit Response Let RESTART_Q_HI = FALSE End Response /* /* We use "User Function" because we want to explictly disable /* all the keys we've defined (like the arrow keys). /* This is easier than redefining all those function responses /* in this field. /* We also want to disable all DECforms defaults (Builtin Function) /* and we don't want the help message to come out for any /* undefined functions either. /*/ Function Response User Function End Response Function Response Builtin Function End Response Function Response Undefined Function End Response /* /* Since we used "User Function" above, we have to now re-declare /* any keys that we DO want /*/ Function Response QUIT Include QUIT_ALL End Response Function Response RETURN_KEY Include RESET_ALL End Response Function Response WAIT_KEY Include WAIT_CHANGE End Response Function Response REPAINT Refresh All End Response Function Response SHOW_SCORE Include TOGGLE_SCORE_DISPLAY End Response /* /* Since we used the "Function Response User" above, /* we cancelled all our key definitions. /* /* In this case, however, we still want the help key to /* work! Since we know this field is simply going to /* activate a help panel, we can use the DECforms default /* definitions for the help keys (PF2 and HELP). /*/ Builtin Function Response NEXT HELP {Use DECforms default} /* /* When we want this field to be visible, we set RESTART_Q_HI /* to true. This turns on the reverse highlight, and lets /* the value ("Press return...") be displayed. When RESTART_Q_HI /* is false, the highlight is turned off, and blanks are displayed. /* This effectively removes the prompt from the screen. /*/ Display NORMAL_TEXT %Keypad_Application Highlight REVERSE_TEXT When RESTART_Q_HI = TRUE Output "" When RESTART_Q_HI = FALSE End Field End Panel /* /* Here are the 4 "boxes", put in separate panels/viewports so that they /* can have unique colors on color monitors. /* /* This would be overkill if you were doing a monochrome version; you /* would simply put these icons directly on the Main_Panel. /*/ Panel PANEL_A Viewport VP_A Apply Field Default BOX_DEFAULT Icon BOX_A Display BOX_ATTR_NORMAL Highlight BOX_ATTR_FLASH When FLASH_NOW = "A" Literal Text Line 1 Column 1 Value " " Display Character Set Private_Rule End Literal Literal Text Next Line Same Column Value " " Display Character Set Private_Rule End Literal Literal Text Next Line Same Column Value " " Display Character Set Private_Rule End Literal End Icon End Panel Panel PANEL_B Viewport VP_B Apply Field Default BOX_DEFAULT Icon BOX_B Display BOX_ATTR_NORMAL Highlight BOX_ATTR_FLASH When FLASH_NOW = "B" Literal Text Line 1 Column 1 Value " " Display Character Set Private_Rule End Literal Literal Text Next Line Same Column Value " " Display Character Set Private_Rule End Literal Literal Text Next Line Same Column Value " " Display Character Set Private_Rule End Literal End Icon End Panel Panel PANEL_C Viewport VP_C Apply Field Default BOX_DEFAULT Icon BOX_C Display BOX_ATTR_NORMAL Highlight BOX_ATTR_FLASH When FLASH_NOW = "C" Literal Text Line 1 Column 1 Value " " Display Character Set Private_Rule End Literal Literal Text Next Line Same Column Value " " Display Character Set Private_Rule End Literal Literal Text Next Line Same Column Value " " Display Character Set Private_Rule End Literal End Icon End Panel Panel PANEL_D Viewport VP_D Apply Field Default BOX_DEFAULT Icon BOX_D Display BOX_ATTR_NORMAL Highlight BOX_ATTR_FLASH When FLASH_NOW = "D" Literal Text Line 1 Column 1 Value " " Display Character Set Private_Rule End Literal Literal Text Next Line Same Column Value " " Display Character Set Private_Rule End Literal Literal Text Next Line Same Column Value " " Display Character Set Private_Rule End Literal End Icon End Panel Help Panel MAIN_HELP /* /* This is the screenful of text that appears when the user /* asks for instructions (the HELP key). /*/ Viewport VP_MAIN { Main viewport (same as game board) } /* /* Clear the message area before displaying the text /*/ Entry Response Message "" End Response /* /* In case any message comes out during help, we want to /* clear the message area before returning. /*/ Exit Response Message " " End Response /* /* As before, we want to catch all keys, and have them /* give a consistent message /*/ Function Response Builtin Function Message NO_MORE_HELP_MSG End Response /* /* For consistency (to the user) we want the same message to come /* out for any keys that are completely undefined (by this IFDL /* or by DECforms). /*/ Function Response Undefined Function Message NO_MORE_HELP_MSG End Response /* /* Earlier, we used "Function Response User Function" to disable /* all user defined functions. In this case (simply to show /* another method of doing a similar thing) we are re-defining /* all the keys that we DON'T want. Keys like QUIT and REFRESH /* will still have our definitions we gave them at layout level. /*/ Function Response SELECT_A Message NO_MORE_HELP_MSG End Response Function Response SELECT_B Message NO_MORE_HELP_MSG End Response Function Response SELECT_C Message NO_MORE_HELP_MSG End Response Function Response SELECT_D Message NO_MORE_HELP_MSG End Response /* /* We want the RETURN key to exit help, instead of the DECforms /* default of PF1-Help /*/ Function Response RETURN_KEY Exit Help End Response /* /* And the contents of the help panel (all text) /*/ Literal Text Line 2 Column 17 Value " COPYCAT INSTRUCTIONS " Display HELP_TITLE_TEXT Font Size Double Wide End Literal /* /* The help text /*/ Literal Text Line 4 Column 5 Value "The object of this game is to duplicate the series of flashing boxes." Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "This Form will 'flash' a series of boxes. Then you press the corre-" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "sponding keys to match the sequence. If you do it correctly, the" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "Form will make the series one flash longer, and show it to you again." Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "If you miss, the Form will start over with a new sequence." Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "Press F10 (or Ctrl/Z) to stop the" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "game. Press PF3 to show score. Use these keypad keys:" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "(On color terminals, each box is a" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "different color.) 8" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "If the flashing occurs too quickly 4 X 6" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "or too slowly, press PF4 to change" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "the time delays. This is necessary 2" Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "for VAXstations and dialup lines." Display NORMAL_TEXT End Literal Literal Text Next Line Same Column Value "" Display NORMAL_TEXT End Literal /* /* Boxes around the key diagram /*/ Literal Rectangle Line 14 Column 57 Line 16 Column 61 Display NORMAL_TEXT End Literal Literal Rectangle Line 16 Column 52 Line 18 Column 56 Display NORMAL_TEXT End Literal Literal Rectangle Line 16 Column 62 Line 18 Column 66 Display NORMAL_TEXT End Literal Literal Rectangle Line 18 Column 57 Line 20 Column 61 Display NORMAL_TEXT End Literal Literal Text Line 23 Column 25 Value " Press RETURN to continue... " Display BOLD_TEXT End Literal Icon WAIT_HERE No Data Input Message NO_MORE_HELP_MSG Display NORMAL_TEXT Literal Text Same Line Next Column Value " " End Literal End Icon End Panel End Layout End Form