Wendell's Hidden Word Search Puzzle Generator

This is a COBOL program written for the AS/400.
Contains a nifty random number generator.


       IDENTIFICATION DIVISION.
      *
      * Generate a Hidden Word Search Puzzle
      * By Wendell Clifton
      * Written 04/25/1997
      *
      * This program contains a random number generator that can
      * generate up to 16777216 pseudorandom numbers before the
      * sequence repeats.
      *
       PROGRAM-ID.  UWLC0106UP.
       AUTHOR. WENDELL CLIFTON
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT HDWORD
               ASSIGN TO DISK-HDWORD
           .
           SELECT PRTOUT
               ASSIGN TO PRINTER-QSYSPRT
           .
       DATA DIVISION.
       FILE SECTION.
      *
       FD  HDWORD.
       01  HDWORD-REC.
           05  INP-SEQ                 PIC  9(04)V9(02).
           05  INP-DAT                 PIC  9(06).
           05  INP-DTA                 PIC  X(80).
       FD  PRTOUT
           RECORD CONTAINS 132 CHARACTERS
           LABEL RECORDS ARE STANDARD
           DATA RECORD IS PRTOUT-REC.
       01  PRTOUT-REC                  PIC  X(132).
      /
       WORKING-STORAGE SECTION.
       01  HDWORD-ATEND-SW             PIC  X(01)  VALUE SPACES.
       01  PRTOUT-NAME                 PIC  X(08)  VALUE "PRTOUT".
       01  PRTOUT-NAME-DT              PIC  X(60)  VALUE SPACES.
       01  PRTOUT-STATUS.
           05  PRTOUT-OPEN-SW          PIC  X(01)  VALUE ZEROES.
       01  PRTOUT-LN-COUNT             PIC  9(02)  VALUE ZEROES.
       01  PRTOUT-PG-COUNT             PIC  9(06)  VALUE ZEROES.
       01  PRTOUT-FSPC-LINES           PIC  9(02)  VALUE ZEROES.
      *
       01  RND-VARS.
           05  RND-MOD                 PIC S9(09)  COMP-3
                                                   VALUE 16777216.
           05  RND-SEED                PIC S9(16)  COMP-3.
           05  RND-RANGE               PIC S9(16)  COMP-3.
           05  RND-NBR                 PIC S9(16)  COMP-3.
           05  RND-DATE                PIC  9(08).
           05  RND-TIME                PIC  9(08).
           05  RND-SRC-X.
               10  RND-SRC1            PIC  X(02).
               10  RND-SRC2            PIC  X(02).
               10  RND-SRC3            PIC  X(02).
               10  RND-SRC4            PIC  X(02).
               10  RND-SRC5            PIC  X(02).
           05  RND-SRC                 REDEFINES RND-SRC-X
                                       PIC  9(10).
           05  RND-TGT-X.
               10  RND-TGT1            PIC  X(02).
               10  RND-TGT2            PIC  X(02).
               10  RND-TGT3            PIC  X(02).
               10  RND-TGT4            PIC  X(02).
               10  RND-TGT5            PIC  X(02).
           05  RND-TGT                 REDEFINES RND-TGT-X
                                       PIC  9(10).
      /
       01  WS-FIELDS.
           05  ZOFF                    PIC  X(01)  VALUE "0".
           05  ZON                     PIC  X(01)  VALUE "1".
           05  PGM-RTN-CDE             PIC  X(01).
           05  SUB1                    PIC S9(07)  COMP-3.
           05  SUB2                    PIC S9(07)  COMP-3.
           05  SUB3                    PIC S9(07)  COMP-3.
           05  SUB4                    PIC S9(07)  COMP-3.
           05  SUB5                    PIC S9(07)  COMP-3.
      * Title of the puzzle
           05  HW-TITLE                PIC  X(80).
      * Sum of all the letters in all the words
           05  HW-LTR-CNT              PIC S9(07)  COMP-3.
      * Puzzle size - varies until a valid puzzle is created
           05  HW-PZL-SZE              PIC S9(07)  COMP-3.
      * Puzzle size - final size of a finished puzzle
           05  HW-PZL-SZE-FNL          PIC S9(07)  COMP-3.
      * Maximum puzzle size
           05  HW-PZL-SZE-MAX          PIC S9(07)  COMP-3  VALUE 80.
      * Number of times a puzzle size has been tried
           05  PZ-CNT                  PIC S9(07)  COMP-3.
      * Maximum number of times a puzzle size can be tried
           05  PZ-MAX                  PIC S9(07)  COMP-3  VALUE 9.
      * Number of words remaining to place in puzzle
           05  RM-CNT                  PIC S9(07)  COMP-3.
      * Number of words of the same size
           05  RM-RNG                  PIC S9(07)  COMP-3.
      * Size of a word
           05  WS-SIZE                 PIC S9(07)  COMP-3.
      * One word of the puzzle
           05  WS-WORD.
               10  WS-CHAR             PIC  X(01)  OCCURS 80.
      * A generic print line
           05  PT-LINE.
               10  PT-POS              PIC  X(01)  OCCURS 132.
      * Word list columns
           05  WL-COL                  PIC S9(07)  COMP-3.
      * Word list rows
           05  WL-ROW                  PIC S9(07)  COMP-3.
      * Word list width of one column
           05  WL-WTH                  PIC S9(07)  COMP-3.
      * Width of printed page
           05  PG-WTH                  PIC S9(07)  COMP-3  VALUE 80.
      * Width of an individual word
           05  WD-WTH                  PIC S9(07)  COMP-3  VALUE 80.
      * Position of a word in word list
           05  PZL-WORD                PIC S9(07)  COMP-3  VALUE 80.
      * Number of valid positions
           05  VL-POS                  PIC S9(07)  COMP-3.
      * Number of hits
           05  VL-HIT                  PIC S9(07)  COMP-3.
      * Valid random table entry
           05  VL-RND                  PIC S9(07)  COMP-3.
      * Position row
           05  PS-ROW                  PIC S9(07)  COMP-3.
      * Position column
           05  PS-COL                  PIC S9(07)  COMP-3.
      * Row increment
           05  PS-ROW-INC              PIC S9(07)  COMP-3.
      * Column increment
           05  PS-COL-INC              PIC S9(07)  COMP-3.
      * Valid position indicator
           05  PS-VAL-IND              PIC  X(01).
      * Tables
       01  HW-TABLES.
      * Number of words in the puzzle
           05  HW-CNT                  PIC S9(07)  COMP-3.
      * Input table of words
           05  HW-INP                  PIC  X(80)  OCCURS 1000.
      * Table of words sorted alphanumerically
           05  HW-ALP                  PIC  X(80)  OCCURS 1000.
      * Table of words sorted by size and alphanumerically
           05  HW-SIZE-TABLE.
               10  HW-SZE              PIC  X(80)  OCCURS 1000.
               10  HW-SLN              PIC S9(07)  OCCURS 1000.
      * Table of words remaining to be used
           05  HW-REMAINING.
               10  HW-RMN              PIC  X(80)  OCCURS 1000.
               10  HW-RLN              PIC S9(07)  OCCURS 1000.
      * Hidden word puzzle
           05  HW-PZL.
               10  HW-ROW              OCCURS 132.
                   15  HW-COL          OCCURS 132.
                       20  HW-ENT      PIC  X(01).
      * Value of a specific puzzle position
           05  HW-POS-CHAR             PIC  X(01).
      * Number of entries in valid position table
           05  HW-VLD-CNT              PIC S9(07)  COMP-3.
      * Table of valid positions
           05  HW-VLD-POS              PIC S9(07)  COMP-3
                                       OCCURS 100000.
      * Table of valid hits
           05  HW-VLD-HIT              PIC S9(07)  COMP-3
                                       OCCURS 100000.
      * Table of directions
           05  HW-DIR-TABLE.
      * 1
               10  FILLER              PIC S9(03)  COMP-3  VALUE  0.
               10  FILLER              PIC S9(03)  COMP-3  VALUE  1.
      * 2
               10  FILLER              PIC S9(03)  COMP-3  VALUE -1.
               10  FILLER              PIC S9(03)  COMP-3  VALUE  1.
      * 3
               10  FILLER              PIC S9(03)  COMP-3  VALUE -1.
               10  FILLER              PIC S9(03)  COMP-3  VALUE  0.
      * 4
               10  FILLER              PIC S9(03)  COMP-3  VALUE -1.
               10  FILLER              PIC S9(03)  COMP-3  VALUE -1.
      * 5
               10  FILLER              PIC S9(03)  COMP-3  VALUE  0.
               10  FILLER              PIC S9(03)  COMP-3  VALUE -1.
      * 6
               10  FILLER              PIC S9(03)  COMP-3  VALUE  1.
               10  FILLER              PIC S9(03)  COMP-3  VALUE -1.
      * 7
               10  FILLER              PIC S9(03)  COMP-3  VALUE  1.
               10  FILLER              PIC S9(03)  COMP-3  VALUE  0.
      * 8
               10  FILLER              PIC S9(03)  COMP-3  VALUE  1.
               10  FILLER              PIC S9(03)  COMP-3  VALUE  1.
           05  HW-DIR-TBL              REDEFINES HW-DIR-TABLE
                                       OCCURS 8.
               10  HW-DIR-ROW          PIC S9(03)  COMP-3.
               10  HW-DIR-COL          PIC S9(03)  COMP-3.
      *
       01  HW-POS-TABLES.
      * Number of entries in position table
           05  HW-POS-CNT              PIC S9(07)  COMP-3.
      * Table of all positions
           05  HW-POS-TABLE            OCCURS 100000.
               10  HW-PT-ROW           PIC S9(07)  COMP-3.
               10  HW-PT-COL           PIC S9(07)  COMP-3.
               10  HW-PT-DIR           PIC S9(07)  COMP-3.
               10  HW-PT-ROW-INC       PIC S9(07)  COMP-3.
               10  HW-PT-COL-INC       PIC S9(07)  COMP-3.
               10  HW-PT-MAX-POS       PIC S9(07)  COMP-3.
           05  HW-POS-ENTRY.
               10  HW-PE-ROW           PIC S9(07)  COMP-3.
               10  HW-PE-COL           PIC S9(07)  COMP-3.
               10  HW-PE-DIR           PIC S9(07)  COMP-3.
               10  HW-PE-ROW-INC       PIC S9(07)  COMP-3.
               10  HW-PE-COL-INC       PIC S9(07)  COMP-3.
               10  HW-PE-MAX-POS       PIC S9(07)  COMP-3.
      *
      * Table of final positions
       01  HW-FNL-POSITION.
           05  HW-FNL-POS              OCCURS 1000.
               10  HW-FP-ROW           PIC S9(07)  COMP-3.
               10  HW-FP-COL           PIC S9(07)  COMP-3.
               10  HW-FP-DIR           PIC S9(07)  COMP-3.
               10  HW-FP-ROW-INC       PIC S9(07)  COMP-3.
               10  HW-FP-COL-INC       PIC S9(07)  COMP-3.
               10  HW-FP-MAX-POS       PIC S9(07)  COMP-3.
      *
      * Puzzle instructions
       01  PRT-INST.
           05  PRT-INST1               PIC X(80)  VALUE
           "Solve the hidden word search puzzle.".
           05  PRT-INST2               PIC X(80)  VALUE
           "Words may be horizontal, vertical, diagonal, forward and bac
      -    "kward.".
           05  PRT-INST3               PIC X(80)  VALUE
           "Words may cross and overlap.".
           05  PRT-INST4               PIC X(80)  VALUE
           "Each word has a unique location in the puzzle.".
           05  PRT-INST5               PIC X(80)  VALUE
           "Words found in the puzzle but not in the word list are unint
      -    "entional.".
      *
      * Solution header
       01  SL-HDR.
           05  FILLER                  PIC  X(50)  VALUE
           "    NBR      ROW   COLUMN      DIR  WORD          ".
      *    "12345678901234567890123456789012345678901234567890".
      *
      * Solution print line
       01  SL-REC.
           05  SL-SEQ                  PIC  Z(07)-.
           05  FILLER                  PIC  X(01)  VALUE SPACES.
           05  SL-ROW                  PIC  Z(07)-.
           05  FILLER                  PIC  X(01)  VALUE SPACES.
           05  SL-COL                  PIC  Z(07)-.
           05  FILLER                  PIC  X(01)  VALUE SPACES.
           05  SL-DIR                  PIC  Z(07)-.
           05  FILLER                  PIC  X(01)  VALUE SPACES.
           05  SL-WORD                 PIC  X(80).
      *
      * Obsolete print line
       01  PRT-REC.
           05  PRT-SEQ                 PIC  9(07)-.
           05  FILLER                  PIC  X(01)  VALUE SPACES.
           05  PRT-ROW                 PIC  9(07)-.
           05  FILLER                  PIC  X(01)  VALUE SPACES.
           05  PRT-COL                 PIC  9(07)-.
           05  FILLER                  PIC  X(01)  VALUE SPACES.
           05  PRT-DIR                 PIC  9(07)-.
           05  FILLER                  PIC  X(01)  VALUE SPACES.
           05  PRT-ROW-INC             PIC  9(07)-.
           05  FILLER                  PIC  X(01)  VALUE SPACES.
           05  PRT-COL-INC             PIC  9(07)-.
           05  FILLER                  PIC  X(01)  VALUE SPACES.
           05  PRT-MAX-POS             PIC  9(07)-.
           05  FILLER                  PIC  X(01)  VALUE SPACES.
           05  PRT-VLD-POS             PIC  9(07)-.
      /
       PROCEDURE DIVISION.
       MAINLINE SECTION.
       MAINLINE-SECTION.
      *
      * Initialization
      *
           PERFORM OPEN-OUTPUT-PRTOUT
           MOVE SPACES TO PGM-RTN-CDE
           MOVE SPACES TO HW-POS-TABLES
           PERFORM RND-INIT THRU RND-INIT-EXIT
           PERFORM READ-LIST THRU READ-LIST-EXIT
           IF PGM-RTN-CDE = SPACES
               PERFORM WORD-SORT THRU WORD-SORT-EXIT
           END-IF
           IF PGM-RTN-CDE = SPACES
               PERFORM CALC-SIZE THRU CALC-SIZE-EXIT
           END-IF
      *
      * Create puzzle
      *
           IF PGM-RTN-CDE = SPACES
               PERFORM
                   VARYING HW-PZL-SZE FROM HW-PZL-SZE BY 1
                     UNTIL HW-PZL-SZE > HW-PZL-SZE-MAX
                        OR PGM-RTN-CDE NOT = SPACES
                   PERFORM CALC-ALL-POS THRU CALC-ALL-POS-EXIT
                   PERFORM CREATE-PUZZLE THRU CREATE-PUZZLE-EXIT
                       VARYING PZ-CNT FROM 1 BY 1
                         UNTIL PZ-CNT > PZ-MAX
                            OR PGM-RTN-CDE NOT = SPACES
                   IF PGM-RTN-CDE = ZON
                       MOVE SPACES TO PGM-RTN-CDE
                   END-IF
               END-PERFORM
           END-IF
      *
      * Print puzzle
      *
           IF PGM-RTN-CDE = ZOFF
               PERFORM PRINT-PUZZLE THRU PRINT-PUZZLE-EXIT
               PERFORM PRINT-WORD-LIST THRU PRINT-WORD-LIST-EXIT
               PERFORM PRINT-SOLUTION-LIST THRU PRINT-SOLUTION-LIST-EXIT
               PERFORM ADVANCE-PRTOUT-PAGE
               PERFORM FILL-PUZZLE THRU FILL-PUZZLE-EXIT
               PERFORM PRINT-PUZZLE THRU PRINT-PUZZLE-EXIT
               PERFORM PRINT-WORD-LIST THRU PRINT-WORD-LIST-EXIT
               PERFORM PRINT-INST THRU PRINT-INST-EXIT
           ELSE
               MOVE "Puzzle not valid" TO PRTOUT-REC
               PERFORM WRITE-PRTOUT
           END-IF
      *    PERFORM PRINT-LIST THRU PRINT-LIST-EXIT
      *
           DISPLAY "Word count=", HW-CNT,
                   "  Final size=", HW-PZL-SZE-FNL,
                   "  Letters=", HW-LTR-CNT,
                   "  Columns=", WL-COL, "  Rows=", WL-ROW,
                   "  Valid count=", HW-VLD-CNT

           PERFORM CLOSE-PRTOUT
           GOBACK.
      /
      *
      * Read list of words from file
      *
       READ-LIST.
           OPEN INPUT HDWORD
           MOVE ZEROES TO HW-CNT
           READ HDWORD
               AT END MOVE ZON TO HDWORD-ATEND-SW
           END-READ
           IF HDWORD-ATEND-SW = SPACES
              MOVE INP-DTA TO HW-TITLE
               READ HDWORD
                   AT END MOVE ZON TO HDWORD-ATEND-SW
               END-READ
           END-IF
           PERFORM
             UNTIL HDWORD-ATEND-SW = ZON
                OR INP-DTA = SPACES
               ADD 1 TO HW-CNT
               MOVE INP-DTA TO HW-INP (HW-CNT)
               READ HDWORD
                   AT END MOVE ZON TO HDWORD-ATEND-SW
               END-READ
           END-PERFORM
           IF HW-CNT = ZEROES
               MOVE ZON TO PGM-RTN-CDE
           END-IF
           CLOSE HDWORD
           .
       READ-LIST-EXIT. EXIT.
      /
       WORD-SORT.
      *
      * Load tables
      *
           MOVE ZEROES TO HW-LTR-CNT
           MOVE ZEROES TO HW-SLN (1)
           PERFORM VARYING SUB1 FROM 1 BY 1
             UNTIL SUB1 > HW-CNT
               MOVE HW-INP (SUB1) TO HW-ALP (SUB1)
               MOVE HW-INP (SUB1) TO HW-SZE (SUB1), WS-WORD
               PERFORM VARYING SUB2 FROM 1 BY 1
                 UNTIL SUB2 > WD-WTH
                    OR WS-CHAR (SUB2) = SPACES
                   CONTINUE
               END-PERFORM
               SUBTRACT 1 FROM SUB2
               MOVE SUB2 TO HW-SLN (SUB1)
               ADD SUB2 TO HW-LTR-CNT
           END-PERFORM
      *
      * Alphanumeric sort
      *
           IF HW-CNT > 1
               PERFORM VARYING SUB1 FROM 1 BY 1
                 UNTIL SUB1 = HW-CNT
                   MOVE SUB1 TO SUB3
                   ADD 1 TO SUB1 GIVING SUB2
                   PERFORM VARYING SUB2 FROM SUB2 BY 1
                     UNTIL SUB2 > HW-CNT
                       IF HW-ALP (SUB2) < HW-ALP (SUB3)
                           MOVE SUB2 TO SUB3
                       END-IF
                   END-PERFORM
                   IF SUB3 > SUB1
                       MOVE HW-ALP (SUB1) TO WS-WORD
                       MOVE HW-ALP (SUB3) TO HW-ALP (SUB1)
                       MOVE WS-WORD TO HW-ALP (SUB3)
                   END-IF
               END-PERFORM
           END-IF
      *
      * Size sort
      *
           IF HW-CNT > 1
               PERFORM VARYING SUB1 FROM 1 BY 1
                 UNTIL SUB1 = HW-CNT
                   MOVE SUB1 TO SUB3
                   ADD 1 TO SUB1 GIVING SUB2
                   PERFORM VARYING SUB2 FROM SUB2 BY 1
                     UNTIL SUB2 > HW-CNT
                       IF HW-SLN (SUB2) > HW-SLN (SUB3)
                           MOVE SUB2 TO SUB3
                       ELSE IF HW-SLN (SUB2) = HW-SLN (SUB3)
                          AND HW-SZE (SUB2) < HW-SZE (SUB3)
                           MOVE SUB2 TO SUB3
                       END-IF END-IF
                   END-PERFORM
                   IF SUB3 > SUB1
                       MOVE HW-SZE (SUB1) TO WS-WORD
                       MOVE HW-SZE (SUB3) TO HW-SZE (SUB1)
                       MOVE WS-WORD TO HW-SZE (SUB3)
                       MOVE HW-SLN (SUB1) TO WS-SIZE
                       MOVE HW-SLN (SUB3) TO HW-SLN (SUB1)
                       MOVE WS-SIZE TO HW-SLN (SUB3)
                   END-IF
               END-PERFORM
           END-IF
           .
       WORD-SORT-EXIT. EXIT.
      /
      *
      * Calculate starting puzzle dimensions.
      * X and Y are the same size.
      *
       CALC-SIZE.
           MOVE ZEROES TO SUB2
           MOVE ZEROES TO HW-PZL-SZE
           PERFORM UNTIL SUB2 > ZEROES
               ADD 1 TO HW-PZL-SZE
               COMPUTE SUB1 = HW-PZL-SZE * HW-PZL-SZE
               IF SUB1 NOT < HW-LTR-CNT
                   MOVE 1 TO SUB2
               END-IF
           END-PERFORM
           SUBTRACT 5 FROM HW-PZL-SZE
      *
           IF HW-PZL-SZE < HW-SLN (1)
               MOVE HW-SLN (1) TO HW-PZL-SZE
           END-IF
           IF HW-PZL-SZE > HW-PZL-SZE-MAX
               MOVE ZON TO PGM-RTN-CDE
               DISPLAY "Puzzle is too large to print"
           END-IF
           .
       CALC-SIZE-EXIT. EXIT.
      /
      *
      * Calculate all positions in puzzle
      *
       CALC-ALL-POS.
           MOVE ZEROES TO HW-POS-CNT
           MOVE HW-SLN (1) TO WS-SIZE
           PERFORM VARYING HW-PE-ROW FROM 1 BY 1
             UNTIL HW-PE-ROW > HW-PZL-SZE
               PERFORM VARYING HW-PE-COL FROM 1 BY 1
                 UNTIL HW-PE-COL > HW-PZL-SZE
                   PERFORM VARYING HW-PE-DIR FROM 1 BY 1
                     UNTIL HW-PE-DIR > 8
                       MOVE HW-PE-ROW TO PS-ROW
                       MOVE HW-PE-COL TO PS-COL
                       MOVE HW-DIR-ROW (HW-PE-DIR) TO HW-PE-ROW-INC
                       MOVE HW-DIR-COL (HW-PE-DIR) TO HW-PE-COL-INC
                       MOVE SPACES TO PS-VAL-IND
                       PERFORM VARYING HW-PE-MAX-POS FROM 1 BY 1
                         UNTIL HW-PE-MAX-POS > WS-SIZE
                            OR PS-VAL-IND NOT = SPACES
                           ADD HW-PE-ROW-INC TO PS-ROW
                           ADD HW-PE-COL-INC TO PS-COL
                           IF PS-ROW < 1
                              OR PS-COL < 1
                              OR PS-ROW > HW-PZL-SZE
                              OR PS-COL > HW-PZL-SZE
                               MOVE ZON TO PS-VAL-IND
                           END-IF
                       END-PERFORM
                       SUBTRACT 1 FROM HW-PE-MAX-POS
                       ADD 1 TO HW-POS-CNT
                       MOVE HW-POS-ENTRY TO HW-POS-TABLE (HW-POS-CNT)
                   END-PERFORM
               END-PERFORM
           END-PERFORM
           .
       CALC-ALL-POS-EXIT. EXIT.
      /
      *
      * Create hidden word search puzzle
      *
       CREATE-PUZZLE.
           MOVE SPACES TO HW-PZL
           MOVE SPACES TO HW-FNL-POSITION
           MOVE HW-SIZE-TABLE TO HW-REMAINING
           MOVE HW-CNT TO RM-CNT
           PERFORM
             UNTIL RM-CNT = ZEROES
                OR PGM-RTN-CDE NOT = SPACES
      * Find number of words the same length as the first word
               PERFORM VARYING SUB1 FROM 1 BY 1
                 UNTIL SUB1 > RM-CNT
                    OR HW-RLN (SUB1) NOT = HW-RLN (1)
                   MOVE SUB1 TO RM-RNG
               END-PERFORM
      *
               PERFORM VARYING RM-RNG FROM RM-RNG BY -1
                 UNTIL RM-RNG < 1
                    OR PGM-RTN-CDE NOT = SPACES
      * Pick a word to place in the puzzle
                   MOVE RM-RNG TO RND-RANGE
                   PERFORM RND-GEN THRU RND-GEN-EXIT
                   ADD 1 TO RND-NBR GIVING PZL-WORD
      * Find all valid positions
                   PERFORM VALID-POSITION THRU VALID-POSITION-EXIT
                   IF PGM-RTN-CDE = SPACES
                       PERFORM CHOSE-POSITION THRU CHOSE-POSITION-EXIT
                   END-IF
      * Remove word from word list
                   SUBTRACT 1 FROM RM-CNT
                   MOVE PZL-WORD TO SUB1, SUB2
                   PERFORM VARYING SUB1 FROM SUB1 BY 1
                     UNTIL SUB1 > RM-CNT
                       ADD 1 TO SUB2
                       MOVE HW-RMN (SUB2) TO HW-RMN (SUB1)
                       MOVE HW-RLN (SUB2) TO HW-RLN (SUB1)
                   END-PERFORM
                   MOVE SPACES TO HW-RMN (SUB2)
                   MOVE ZEROES TO HW-RLN (SUB2)
               END-PERFORM
           END-PERFORM
      *
           IF PGM-RTN-CDE = SPACES
               MOVE ZOFF TO PGM-RTN-CDE
           ELSE
               MOVE SPACES TO PGM-RTN-CDE
           END-IF
           MOVE HW-PZL-SZE TO HW-PZL-SZE-FNL
           DISPLAY "REMAINING=", RM-CNT, "  RTNCDE=", PGM-RTN-CDE,
                   "  SIZE=", HW-PZL-SZE
           .
       CREATE-PUZZLE-EXIT. EXIT.
      /
      *
      * Find all valid positions for one word
      *
       VALID-POSITION.
           MOVE ZEROES TO HW-VLD-CNT
           MOVE HW-RMN (PZL-WORD) TO WS-WORD
           MOVE HW-RLN (PZL-WORD) TO WS-SIZE
           PERFORM VARYING SUB1 FROM 1 BY 1
             UNTIL SUB1 > HW-POS-CNT
               MOVE HW-POS-TABLE (SUB1) TO HW-POS-ENTRY
               IF WS-SIZE NOT > HW-PE-MAX-POS
                   MOVE HW-PE-ROW TO PS-ROW
                   MOVE HW-PE-COL TO PS-COL
                   MOVE SPACES TO PS-VAL-IND
                   MOVE ZEROES TO VL-HIT
                   PERFORM VARYING SUB2 FROM 1 BY 1
                     UNTIL SUB2 > WS-SIZE
                       IF HW-ENT (PS-ROW, PS-COL) = SPACES
                           NEXT SENTENCE
                       ELSE IF HW-ENT (PS-ROW, PS-COL) = WS-CHAR (SUB2)
                           ADD 1 TO VL-HIT
                       ELSE
                           MOVE ZON TO PS-VAL-IND
                           MOVE WS-SIZE TO SUB2
                       END-IF END-IF
                       ADD HW-PE-ROW-INC TO PS-ROW
                       ADD HW-PE-COL-INC TO PS-COL
                   END-PERFORM
                   IF VL-HIT = WS-SIZE
                       MOVE ZON TO PS-VAL-IND
                   END-IF
                   IF PS-VAL-IND = SPACES
                       ADD 1 TO HW-VLD-CNT
                       MOVE SUB1 TO HW-VLD-POS (HW-VLD-CNT)
                       MOVE VL-HIT TO HW-VLD-HIT (HW-VLD-CNT)
                   END-IF
               END-IF
               IF HW-VLD-CNT = ZEROES
                   MOVE ZON TO PGM-RTN-CDE
               END-IF
           END-PERFORM
           .
       VALID-POSITION-EXIT. EXIT.
      /
      *
      * Place word in puzzle
      *
       CHOSE-POSITION.
      * Find highest hits and number of positions with highest hits
           MOVE ZEROES TO VL-HIT, VL-POS
           PERFORM VARYING SUB1 FROM 1 BY 1
             UNTIL SUB1 > HW-VLD-CNT
               IF HW-VLD-HIT (SUB1) > VL-HIT
                   MOVE HW-VLD-HIT (SUB1) TO VL-HIT
                   MOVE ZEROES TO VL-POS
               END-IF
               IF HW-VLD-HIT (SUB1) = VL-HIT
                   ADD 1 TO VL-POS
               END-IF
           END-PERFORM
      * Pick an entry from the highest count entries
           MOVE VL-POS TO RND-RANGE
           PERFORM RND-GEN THRU RND-GEN-EXIT
           ADD 1 TO RND-NBR GIVING VL-RND
           MOVE ZEROES TO SUB2, VL-POS
           PERFORM VARYING SUB1 FROM 1 BY 1
             UNTIL SUB2 = VL-RND
               IF HW-VLD-HIT (SUB1) = VL-HIT
                  ADD 1 TO SUB2
                  MOVE SUB1 TO VL-POS
               END-IF
           END-PERFORM
      * Save entry in final solution table
           MOVE HW-VLD-POS (VL-POS) TO SUB1
           MOVE HW-POS-TABLE (SUB1) TO HW-POS-ENTRY
           PERFORM VARYING SUB1 FROM 1 BY 1
             UNTIL SUB1 > HW-CNT
               IF WS-WORD = HW-ALP (SUB1)
                  AND HW-FNL-POS (SUB1) = SPACES
                   MOVE HW-POS-ENTRY TO HW-FNL-POS (SUB1)
                   MOVE HW-CNT TO SUB1
               END-IF
           END-PERFORM
      * Place word in puzzle
           PERFORM VARYING SUB1 FROM 1 BY 1
             UNTIL SUB1 > WS-SIZE
               MOVE WS-CHAR (SUB1) TO HW-ENT (HW-PE-ROW, HW-PE-COL)
               ADD HW-PE-ROW-INC TO HW-PE-ROW
               ADD HW-PE-COL-INC TO HW-PE-COL
           END-PERFORM
           .
       CHOSE-POSITION-EXIT. EXIT.
      /
      *
      * Print word list
      *
       PRINT-SOLUTION-LIST.
           MOVE SPACES TO SL-REC
           PERFORM ADVANCE-PRTOUT-PAGE
           MOVE SL-HDR TO PRTOUT-REC
           PERFORM WRITE-PRTOUT
           PERFORM VARYING SUB1 FROM 1 BY 1
             UNTIL SUB1 > HW-CNT
               MOVE SUB1 TO SL-SEQ
               MOVE HW-FNL-POS (SUB1) TO HW-POS-ENTRY
               MOVE HW-PE-ROW TO SL-ROW
               MOVE HW-PE-COL TO SL-COL
               MOVE HW-PE-DIR TO SL-DIR
               MOVE HW-ALP (SUB1) TO SL-WORD
               MOVE SL-REC TO PRTOUT-REC
               PERFORM WRITE-PRTOUT
           END-PERFORM
           .
       PRINT-SOLUTION-LIST-EXIT. EXIT.
      /
      *
      * Print puzzle
      *
       PRINT-PUZZLE.
           MOVE HW-TITLE TO PRTOUT-REC
           PERFORM WRITE-PRTOUT
           PERFORM WRITE-PRTOUT
           PERFORM VARYING SUB1 FROM 1 BY 1
             UNTIL SUB1 > HW-PZL-SZE-FNL
               MOVE SPACES TO PT-LINE
               MOVE 1 TO SUB3
               PERFORM VARYING SUB2 FROM 1 BY 1
                 UNTIL SUB2 > HW-PZL-SZE-FNL
                   MOVE HW-ENT (SUB1, SUB2) TO PT-POS (SUB3)
                   ADD 2 TO SUB3
               END-PERFORM
               MOVE PT-LINE TO PRTOUT-REC
               PERFORM WRITE-PRTOUT
           END-PERFORM
           .
       PRINT-PUZZLE-EXIT. EXIT.
      *
      * Print word list
      *
       PRINT-WORD-LIST.
           COMPUTE WL-COL = PG-WTH / (HW-SLN (1) + 2)
           IF WL-COL < 1
               MOVE 1 TO WL-COL
           END-IF
      *
           COMPUTE WL-WTH = PG-WTH / WL-COL
           IF WL-WTH < 1
               MOVE 1 TO WL-WTH
           END-IF
      *
           COMPUTE WL-ROW = HW-CNT / WL-COL
           COMPUTE SUB1 = WL-ROW * WL-COL
           IF SUB1 < HW-CNT
               ADD 1 TO WL-ROW
           END-IF
      *
           PERFORM WRITE-PRTOUT
           PERFORM VARYING SUB1 FROM 1 BY 1
             UNTIL SUB1 > WL-ROW
               MOVE SPACES TO PT-LINE
               MOVE ZEROES TO SUB5
               PERFORM VARYING SUB2 FROM SUB1 BY WL-ROW
                 UNTIL SUB2 > HW-CNT
                   MOVE SUB5 TO SUB4
                   MOVE HW-ALP (SUB2) TO WS-WORD
                   PERFORM VARYING SUB3 FROM 1 BY 1
                     UNTIL SUB3 > WD-WTH
                        OR WS-CHAR (SUB3) = SPACES
                       ADD 1 TO SUB4
                       MOVE WS-CHAR (SUB3) TO PT-POS (SUB4)
                   END-PERFORM
                   ADD WL-WTH TO SUB5
               END-PERFORM
               MOVE PT-LINE TO PRTOUT-REC
               PERFORM WRITE-PRTOUT
           END-PERFORM
           .
       PRINT-WORD-LIST-EXIT. EXIT.
      *
      * Fill the empty spaces in the puzzle
      *
       FILL-PUZZLE.
           PERFORM VARYING SUB1 FROM 1 BY 1
             UNTIL SUB1 > HW-PZL-SZE-FNL
               PERFORM VARYING SUB2 FROM 1 BY 1
                 UNTIL SUB2 > HW-PZL-SZE-FNL
                   IF HW-ENT (SUB1, SUB2) = SPACES
                       MOVE SPACES TO PS-VAL-IND
                       PERFORM UNTIL PS-VAL-IND NOT = SPACES
                           MOVE HW-PZL-SZE-FNL TO RND-RANGE
                           PERFORM RND-GEN THRU RND-GEN-EXIT
                           ADD 1 TO RND-NBR GIVING SUB3
                           MOVE HW-PZL-SZE-FNL TO RND-RANGE
                           PERFORM RND-GEN THRU RND-GEN-EXIT
                           ADD 1 TO RND-NBR GIVING SUB4
                           IF HW-ENT (SUB3, SUB4) NOT = SPACES
                               MOVE ZON TO PS-VAL-IND
                               MOVE HW-ENT (SUB3, SUB4) TO
                                    HW-ENT (SUB1, SUB2)
                           END-IF
                       END-PERFORM
                   END-IF
               END-PERFORM
           END-PERFORM
           .
       FILL-PUZZLE-EXIT. EXIT.
      *
      * Print instructions
      *
       PRINT-INST.
           PERFORM WRITE-PRTOUT
           MOVE PRT-INST1 TO PRTOUT-REC
           PERFORM WRITE-PRTOUT
           MOVE PRT-INST2 TO PRTOUT-REC
           PERFORM WRITE-PRTOUT
           MOVE PRT-INST3 TO PRTOUT-REC
           PERFORM WRITE-PRTOUT
           MOVE PRT-INST4 TO PRTOUT-REC
           PERFORM WRITE-PRTOUT
           MOVE PRT-INST5 TO PRTOUT-REC
           PERFORM WRITE-PRTOUT
           .
       PRINT-INST-EXIT. EXIT.
      /
      *
      * Print statistics
      *
       PRINT-LIST.
           PERFORM VARYING SUB1 FROM 1 BY 1
             UNTIL SUB1 > HW-POS-CNT
               MOVE SPACES TO PRT-REC
               MOVE SUB1 TO PRT-SEQ
               MOVE HW-PT-ROW (SUB1) TO PRT-ROW
               MOVE HW-PT-COL (SUB1) TO PRT-COL
               MOVE HW-PT-DIR (SUB1) TO PRT-DIR
               MOVE HW-PT-ROW-INC (SUB1) TO PRT-ROW-INC
               MOVE HW-PT-COL-INC (SUB1) TO PRT-COL-INC
               MOVE HW-PT-MAX-POS (SUB1) TO PRT-MAX-POS
               IF SUB1 NOT > HW-VLD-CNT
                   MOVE HW-VLD-POS (SUB1) TO PRT-VLD-POS
               END-IF
               MOVE PRT-REC TO PRTOUT-REC
               PERFORM WRITE-PRTOUT
           END-PERFORM
           .
       PRINT-LIST-EXIT. EXIT.
      /
      ******************************************************************
      * Random Number Generator Initialization
      *
      * Prepares the Random Number Generator for execution.
      *
      * Call this routine one time during program initialization.
      * The date and time are combined.  The fastest changing
      * digits are switched with the slowest.  This will cause the
      * seed to be significantly different with each execution of
      * the initialization.
      *
      * No user inputs or outputs.
      ******************************************************************
       RND-INIT.
           ACCEPT RND-DATE FROM DATE
           ACCEPT RND-TIME FROM TIME
           ADD RND-DATE, RND-TIME GIVING RND-SRC
           MOVE RND-SRC1 TO RND-TGT5
           MOVE RND-SRC2 TO RND-TGT4
           MOVE RND-SRC3 TO RND-TGT3
           MOVE RND-SRC4 TO RND-TGT2
           MOVE RND-SRC5 TO RND-TGT1
           MOVE RND-TGT TO RND-NBR
           COMPUTE
               RND-SEED = RND-NBR - ((RND-NBR / RND-MOD) * RND-MOD)
           .
       RND-INIT-EXIT. EXIT.
      ******************************************************************
      * Random Number Generator
      *
      * Generates a series of pseudorandom numbers.
      *
      * The seed is altered.
      * The modulus of the result becomes the new seed.
      * The new random number is derived from the new seed.
      * The seed and the random number will always be less than the
      * modulus and never less than zero.
      * 16777216 pseudorandom numbers are generated before the
      * sequence repeats.
      *
      * INPUT:   RND-RANGE    Valid values are 1 to 16777216.
      *                       For best results, do not exceed 8388608.
      * ** The input range is not validated.  USER BEWARE. **
      *
      * OUTPUT:  RND-NBR      Valid values are 0 to RND-RANGE - 1
      ******************************************************************
       RND-GEN.
           COMPUTE RND-NBR = (RND-SEED * 3067) + 7
           COMPUTE
               RND-SEED = RND-NBR - ((RND-NBR / RND-MOD) * RND-MOD)
           COMPUTE RND-NBR = (RND-SEED * RND-RANGE) / RND-MOD
               ON SIZE ERROR MOVE ZEROES TO RND-NBR
           .
       RND-GEN-EXIT. EXIT.
      /
       OPEN-OUTPUT-PRTOUT.
           MOVE ZEROS TO PRTOUT-STATUS.
           OPEN OUTPUT PRTOUT.
           MOVE ZON TO PRTOUT-OPEN-SW.
           MOVE SPACES TO PRTOUT-REC.
           MOVE 0 TO PRTOUT-PG-COUNT.
           MOVE 0 TO PRTOUT-LN-COUNT.
      *
       WRITE-PRTOUT.
           WRITE PRTOUT-REC BEFORE ADVANCING 1 LINE.
           MOVE SPACES TO PRTOUT-REC.
           ADD 1 TO PRTOUT-LN-COUNT.
      *
       CLOSE-PRTOUT.
           CLOSE PRTOUT.
           MOVE ZOFF TO PRTOUT-OPEN-SW.

Navigation for the Lost and Bewildered

Wendell's Wonderland: Wendell's Home Page
Wendell's Hidden Word Search Puzzle Page: The hidden word search page

Updated 05/21/1999 guests since
May 21, 1999.