*> chain-reaction.cob IDENTIFICATION DIVISION. PROGRAM-ID. chain-reaction. DATA DIVISION. WORKING-STORAGE SECTION. 01 input-str PIC X(30). COPY "num-elements.cpy". COPY "elements-grid.cpy". COPY "first-elt-coords.cpy". COPY "change-flag.cpy". PROCEDURE DIVISION. ACCEPT input-str UNSTRING input-str DELIMITED BY SPACES INTO num-elements, grid-size *> Read in the elements. CALL "read-in-elements" USING elements-grid-area, num-elements, first-elt-coords *> Display state before any elements have reacted. CALL "display-state" USING elements-grid-area *> Start the chain reaction SET reacting (first-elt-x, first-elt-y) TO TRUE *> Simulate and display the chain reaction. PERFORM UNTIL no-change CALL "display-state" USING elements-grid-area CALL "step-reaction" USING elements-grid-area, change-flag END-PERFORM GOBACK . IDENTIFICATION DIVISION. PROGRAM-ID. read-in-elements. DATA DIVISION. WORKING-STORAGE SECTION. 01 i PIC 99. 01 j PIC 9. 01 input-str PIC X(30). 01 x PIC 99. 01 y PIC 99. 01 element-radius PIC 99. 01 char-num PIC 9(3). 01 prop-dirs PIC X(4). LINKAGE SECTION. COPY "elements-grid.cpy". COPY "num-elements.cpy". COPY "first-elt-coords.cpy". PROCEDURE DIVISION USING elements-grid-area, num-elements, first-elt-coords. PERFORM VARYING i FROM 1 BY 1 UNTIL i > num-elements ACCEPT input-str UNSTRING input-str DELIMITED BY SPACES INTO x, y, element-radius, prop-dirs ADD 1 TO x, y MOVE element-radius TO radius (x, y) COMPUTE char-num = FUNCTION ORD("A") + i - 1 MOVE FUNCTION CHAR(char-num) TO element-char (x, y) MOVE FUNCTION LOWER-CASE(prop-dirs) TO prop-dirs PERFORM VARYING j FROM 1 BY 1 UNTIL j > 4 OR prop-dirs (j:1) = SPACE EVALUATE prop-dirs (j:1) WHEN "u" SET prop-up (x, y) TO TRUE WHEN "d" SET prop-down (x, y) TO TRUE WHEN "l" SET prop-left (x, y) TO TRUE WHEN "r" SET prop-right (x, y) TO TRUE END-EVALUATE END-PERFORM SET is-empty (x, y) TO FALSE IF i = 1 MOVE x TO first-elt-x MOVE y TO first-elt-y END-IF END-PERFORM . END PROGRAM read-in-elements. IDENTIFICATION DIVISION. PROGRAM-ID. display-state. DATA DIVISION. WORKING-STORAGE SECTION. 01 step-counter PIC 99. 01 x PIC 99. 01 y PIC 99. LINKAGE SECTION. COPY "elements-grid.cpy". PROCEDURE DIVISION USING elements-grid-area. DISPLAY "Step " step-counter ":" ADD 1 TO step-counter PERFORM VARYING y FROM 1 BY 1 UNTIL y > grid-size PERFORM VARYING x FROM 1 BY 1 UNTIL x > grid-size IF reacting (x, y) OR reacted (x, y) DISPLAY "X" NO ADVANCING ELSE DISPLAY element-char (x, y) NO ADVANCING END-IF END-PERFORM DISPLAY SPACE END-PERFORM . END PROGRAM display-state. IDENTIFICATION DIVISION. PROGRAM-ID. step-reaction. DATA DIVISION. WORKING-STORAGE SECTION. 01 grid-x PIC 99. 01 grid-y PIC 99. 01 prop-x PIC 99. 01 prop-y PIC 99. LINKAGE SECTION. COPY "elements-grid.cpy". COPY "change-flag.cpy". PROCEDURE DIVISION USING elements-grid-area, change-flag. SET no-change TO TRUE *> Find the next elements that will be reacted. PERFORM VARYING grid-y FROM 1 BY 1 UNTIL grid-y > grid-size AFTER grid-x FROM 1 BY 1 UNTIL grid-x > grid-size IF reacting (grid-x, grid-y) IF prop-up (grid-x, grid-y) PERFORM propagate-up END-IF IF prop-down (grid-x, grid-y) PERFORM propagate-down END-IF IF prop-left (grid-x, grid-y) PERFORM propagate-left END-IF IF prop-right (grid-x, grid-y) PERFORM propagate-right END-IF SET reacted (grid-x, grid-y) TO TRUE END-IF END-PERFORM *> Update the reaction to its next state. PERFORM VARYING grid-y FROM 1 BY 1 UNTIL grid-y > grid-size AFTER grid-x FROM 1 BY 1 UNTIL grid-x > grid-size IF will-react (grid-x, grid-y) SET reacting (grid-x, grid-y) TO TRUE END-IF END-PERFORM GOBACK . propagate-up. MOVE grid-x TO prop-x PERFORM react-element VARYING prop-y FROM grid-y BY 1 UNTIL prop-y > grid-size OR prop-y - grid-y > radius (grid-x, grid-y) . propagate-down. MOVE grid-x TO prop-x PERFORM react-element VARYING prop-y FROM grid-y BY -1 UNTIL prop-y = 0 OR grid-y - prop-y > radius (grid-x, grid-y) . propagate-left. MOVE grid-y TO prop-y PERFORM react-element VARYING prop-x FROM grid-x BY -1 UNTIL prop-x = 0 OR grid-x - prop-x > radius (grid-x, grid-y) . propagate-right. MOVE grid-y TO prop-y PERFORM react-element VARYING prop-x FROM grid-x BY 1 UNTIL prop-x > grid-size OR prop-x - grid-x > radius (grid-x, grid-y) . react-element. IF NOT(is-empty (prop-x, prop-y) OR reacted (prop-x, prop-y) OR reacting (prop-x, prop-y)) SET will-react (prop-x, prop-y) TO TRUE SET no-change TO FALSE END-IF . END PROGRAM step-reaction. *> change-flag.cpy 01 change-flag PIC X. 88 no-change VALUE "Y", FALSE "N". *> elements-grid.cpy 01 elements-grid-area. 03 grid-size PIC 99. 03 elements-x-grid OCCURS 10 TIMES. 05 elements-y-grid OCCURS 10 TIMES. 07 radius PIC 99. 07 element-char PIC X VALUE SPACE. 07 empty-flag PIC X. 88 is-empty VALUE SPACE, FALSE "N". 07 prop-up-flag PIC X. 88 prop-up VALUE "Y". 07 prop-down-flag PIC X. 88 prop-down VALUE "Y". 07 prop-left-flag PIC X. 88 prop-left VALUE "Y". 07 prop-right-flag PIC X. 88 prop-right VALUE "Y". 07 reacting-flag PIC X. 88 reacting VALUE "Y". 88 reacted VALUE "X". 88 will-react VALUE "W". *> first-elt-coords.cpy 01 first-elt-coords. 03 first-elt-x PIC 99. 03 first-elt-y PIC 99. *> num-elements.cpy 01 num-elements PIC 99.