This is the relevant behavior description from the CLIPS Basic Programming Guide, Section 5.4.2 Test Conditional Element:
A test CE is evaluated when all proceeding CEs are satisfied. This
means that a test CE will be evaluated more than once if the
proceeding CEs can be satisfied by more than one group of pattern
entities. In order to cause the reevaluation of a test CE, a pattern
entity matching a CE prior to the test CE must be changed.
When the k-per-col fact is asserted the test CE will be evaluated. If this occurs before any or all a-cell facts have been asserted, then you will not get the same results as if you had asserted all of the a-cell facts first and then the k-per-col fact.
In order to insure predictable behavior, expressions evaluated by the test CE should always return the same value for a specific set of arguments. In this case, the get-unknow-col and get-boat-pieces-col functions can return different values even if the parameter ?col is the same as a previous call.
Some rule-based language provide a "collect" conditional element which allows to easily count the number of facts matching a pattern, but unfortunately CLIPS does not provide this. In order to add this functionality, you'd need to create facts and rules which track the values of interest.
CLIPS (6.31 6/12/19)
CLIPS>
(deftemplate a-cell
(slot id (default-dynamic (gensym*)))
(slot x)
(slot y)
(slot content (allowed-values water left right middle top bot sub unk)))
CLIPS>
(deftemplate track-a-cell
(slot x (default any))
(slot y (default any))
(slot content (default any))
(multislot matches))
CLIPS>
(deffacts trackers
(track-a-cell (x any) (y 9) (content unk)))
CLIPS>
(defrule add-a-cell-match
(declare (salience 10))
?t <- (track-a-cell (x ?x1) (y ?y1) (content ?c1) (matches $?m))
(a-cell (id ?id) (x ?x2) (y ?y2) (content ?c2))
(test (and (not (member$ ?id ?m))
(or (eq ?x1 any) (eq ?x1 ?x2))
(or (eq ?y1 any) (eq ?y1 ?y2))
(or (eq ?c1 any) (eq ?c1 ?c2))))
=>
(modify ?t (matches ?m ?id)))
CLIPS>
(defrule remove-a-cell-match
(declare (salience 10))
?t <- (track-a-cell (x ?x1) (y ?y1) (content ?c1) (matches $?b ?id $?e))
(not (and (a-cell (id ?id) (x ?x2) (y ?y2) (content ?c2))
(test (and (or (eq ?x1 any) (eq ?x1 ?x2))
(or (eq ?y1 any) (eq ?y1 ?y2))
(or (eq ?c1 any) (eq ?c1 ?c2))))))
=>
(modify ?t (matches ?b ?e)))
CLIPS>
(deffacts init
(a-cell (x 0) (y 9) (content water))
(a-cell (x 1) (y 9) (content unk))
(a-cell (x 2) (y 9) (content water))
(a-cell (x 3) (y 9) (content water))
(a-cell (x 5) (y 9) (content water))
(a-cell (x 6) (y 9) (content unk))
(a-cell (x 7) (y 9) (content water))
(a-cell (x 8) (y 9) (content water))
(a-cell (x 9) (y 9) (content water))
(a-cell (x 4) (y 9) (content unk)))
CLIPS> (reset)
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-2 (a-cell (id gen1) (x 0) (y 9) (content water))
f-3 (a-cell (id gen2) (x 1) (y 9) (content unk))
f-4 (a-cell (id gen3) (x 2) (y 9) (content water))
f-5 (a-cell (id gen4) (x 3) (y 9) (content water))
f-6 (a-cell (id gen5) (x 5) (y 9) (content water))
f-7 (a-cell (id gen6) (x 6) (y 9) (content unk))
f-8 (a-cell (id gen7) (x 7) (y 9) (content water))
f-9 (a-cell (id gen8) (x 8) (y 9) (content water))
f-10 (a-cell (id gen9) (x 9) (y 9) (content water))
f-11 (a-cell (id gen10) (x 4) (y 9) (content unk))
f-14 (track-a-cell (x any) (y 9) (content unk) (matches gen10 gen6 gen2))
For a total of 12 facts.
CLIPS> (retract 3 7)
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-2 (a-cell (id gen1) (x 0) (y 9) (content water))
f-4 (a-cell (id gen3) (x 2) (y 9) (content water))
f-5 (a-cell (id gen4) (x 3) (y 9) (content water))
f-6 (a-cell (id gen5) (x 5) (y 9) (content water))
f-8 (a-cell (id gen7) (x 7) (y 9) (content water))
f-9 (a-cell (id gen8) (x 8) (y 9) (content water))
f-10 (a-cell (id gen9) (x 9) (y 9) (content water))
f-11 (a-cell (id gen10) (x 4) (y 9) (content unk))
f-16 (track-a-cell (x any) (y 9) (content unk) (matches gen10))
For a total of 10 facts.
CLIPS> (assert (a-cell (x 1) (y 9) (content unk)))
<Fact-17>
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-2 (a-cell (id gen1) (x 0) (y 9) (content water))
f-4 (a-cell (id gen3) (x 2) (y 9) (content water))
f-5 (a-cell (id gen4) (x 3) (y 9) (content water))
f-6 (a-cell (id gen5) (x 5) (y 9) (content water))
f-8 (a-cell (id gen7) (x 7) (y 9) (content water))
f-9 (a-cell (id gen8) (x 8) (y 9) (content water))
f-10 (a-cell (id gen9) (x 9) (y 9) (content water))
f-11 (a-cell (id gen10) (x 4) (y 9) (content unk))
f-17 (a-cell (id gen11) (x 1) (y 9) (content unk))
f-18 (track-a-cell (x any) (y 9) (content unk) (matches gen10 gen11))
For a total of 11 facts.
CLIPS>