*> 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.