Download
(define (domain plotting)
    
    (:requirements :typing :equality :universal-preconditions :conditional-effects)

    (:types number colour)

    (:constants null wildcard - colour)

    (:predicates
        (hand ?c - colour)
        (coloured ?r ?c - number ?c - colour)

        (succ ?n1 ?n2 - number)
        (gt ?n1 ?n2 - number)
        (pred ?n1 ?n2 - number)
        (lt ?n1 ?n2 - number)

        (distance ?n1 ?n2 ?n3 - number)

        (isfirstcolumn ?n - number) ;; is the first column?
        (islastcolumn ?n - number) ;; is the last column?
        (istoprow ?n - number) ;; is the top row?
        (isbottomrow ?n - number) ;; is the bottom column?

        ;; are we allowed to fire on those?
        (blockedcol ?n - number)
        (blockedrow ?n - number)
    )

    ;; removing a partial row:
    ;;    - we are removing part of a row and there is a next block that has a different
    ;;      colour than the first one.
    (:action shoot-partial-row
        ;; ?r - what row we are shooting
        ;; ?f ?t - from and to, the range that we are trying to remove from the board
        ;; ?c - the colour of the range
        :parameters (?r - number ?t - number ?c - colour)
        :precondition
            (and
                ;; there exists a number that is the successor of the to
                ;; and it has a different colour than c
                (exists (?col - number)
                    (and
                        (succ ?col ?t)
                        (not (coloured ?r ?col ?c))
                        (not (coloured ?r ?col null))))
                      
                ;; exist some column before ?t or ?t that has colour ?c      
                (exists (?col - number)
                    (and
                        (or (lt ?col ?t) (=  ?col ?t))
                        (coloured ?r ?col ?c)))

                ;; stop possible weird stuff
                (not (= ?c null))
                (not (= ?c wildcard))
                ;; colour block and hand is the same (we avoid null movements)
                (or (hand ?c) (hand wildcard))

                ;; from the start, all the blocks up to ?t have either the colour ?c or are null
                (forall (?col - number) 
                    ;; For all columns, either:
                    (or
                        ;; we are out of bounds or
                        (gt ?col ?t)
                 
                        ;; the middle colors and color of ?t are null or the correct one
                        (coloured ?r ?col ?c)
                        (coloured ?r ?col null))))
        :effect
            (and
                ;; Change hands colour and
                ;; The next cell that we cannot remove gets the colour from the hand
                (forall (?nextcolumn - number ?nextcolour - colour)
                    (when 
                        (and
                            ;; there is a new row down this one
                            (succ ?nextcolumn ?t) 
                            ;; and the cell is coloured ?nextcolour
                            (coloured ?r ?nextcolumn ?nextcolour))
                        ;; The hand gets a new colour
                        (and
                            ;; change next cell colour
                            (not (coloured ?r ?nextcolumn ?nextcolour))
                            (coloured ?r ?nextcolumn ?c)
                            ;; change hand colours
                            (hand ?nextcolour)
                            (not (hand ?c))
                            (not (hand wildcard)))))

                ;; finally move everything downwards. we have 2 cases:
                ;;  - we are on the top row
                ;;  - we are on another row
                (forall (?currentrow ?nextrow ?currentcol - number)
                    (and
                        ;; We are on the top row: we must restore the "null" colour
                        (forall (?currentcolor - colour)
                            (when
                                (and 
                                    ;; we are on the top row 
                                    (istoprow ?currentrow)
                                    ;; The column is in the correct range
                                    (or (lt ?currentcol ?t) (= ?currentcol ?t))
                                    ;; We identify the colour of the cell
                                    (coloured ?currentrow ?currentcol ?currentcolor)
                                    ;; avoid contradiction
                                    (not (coloured ?currentrow ?currentcol null)))
                                (and
                                    (not (coloured ?currentrow ?currentcol ?currentcolor))
                                    (coloured ?currentrow ?currentcol null))))

                        ;; We are on any other row: disable the current colour and change the next colour
                        (forall (?currentcolor ?nextcolor - colour)
                            (when
                                ;; when the row is on top of the one we deleted, we "decrease"
                                ;; one position downwards 
                                (and
                                    (lt ?currentrow ?r)            ;; R R R R <- current row 
                                    (succ ?nextrow ?currentrow)    ;; B B B R <- nextrow
                                    ;; The current column is in the correct range (less than the ?t)
                                    (or (lt ?currentcol ?t) (= ?currentcol ?t))

                                    ;; here we ensure that the cells have the pertaining colours
                                    (coloured ?currentrow ?currentcol ?currentcolor)
                                    (coloured ?nextrow ?currentcol ?nextcolor)
                                    ;; avoid the contradiction in the effect if both colours are equal
                                    (not (= ?currentcolor ?nextcolor)))
                                (and ;; and as an effect we change the lower row
                                    (not (coloured ?nextrow ?currentcol ?nextcolor))
                                    (coloured ?nextrow ?currentcol ?currentcolor))))))))

    (:action shoot-column
        ;; ?column - what col we are shooting
        ;; ?t - to, the cell where we stop eating
        ;; ?c - the colour we will act on
        :parameters (?column - number ?t - number ?c - colour)
        :precondition 
            (and
                ;; the successor of the to is of a different colour
                ;; or we are eating the whole column.
                ;; note we don't have to check null colour because gravity
                (or
                    (exists (?row - number)
                        (and
                            (succ ?row ?t)
                            (not (coloured ?row ?column ?c))))
                    (isbottomrow ?t))

                ;; stop possible weird stuff
                (not (= ?c null))
                (not (= ?c wildcard))
                ;; colour block and hand is the same (we avoid null movements)
                (or (hand ?c) (hand wildcard))

                ;; all the middle blocks also have the same colour
                (forall (?row - number) 
                    (or
                        ;; either we are out of bounds or
                        (gt ?row ?t)
                        ;; we are exactly in ?t and it has the correct colour
                        (and (= ?row ?t) (coloured ?row ?column ?c))
                        ;; we are on top of ?t and therefore it can be either ?c or null
                        (and
                            (lt ?row ?t)
                            (or
                                (coloured ?row ?column ?c)
                                (coloured ?row ?column null))))))
        :effect
            (and
                (forall (?runningrow - number)
                    (and
                        ;; we remove the colour of the cells before the "to" (?t)
                        (when 
                            (and
                                (coloured ?runningrow ?column ?c)
                                (or (lt ?runningrow ?t)
                                    (= ?runningrow ?t))
                                (not (coloured ?runningrow ?column null)))
                            (and
                                (coloured ?runningrow ?column null)
                                (not (coloured ?runningrow ?column ?c))))

                        ;; we set the next block colour to the removed cells colour
                        ;; and we set the hands colour to the correct one
                        (forall (?nextcolour - colour)
                            (when
                                (and
                                    (succ ?runningrow ?t)
                                    (coloured ?runningrow ?column ?nextcolour))
                                (and
                                    ;; next cell colour
                                    (not (coloured ?runningrow ?column ?nextcolour))
                                    (coloured ?runningrow ?column ?c)
                                    ;; hand colour
                                    (not (hand wildcard))
                                    (not (hand ?c))
                                    (hand ?nextcolour))))))

                ;; When we are eating the whole column, we set the correct colour onto the hand
                (when
                    (isbottomrow ?t)
                    (and
                        (not (hand wildcard))
                        (hand ?c)))))

    ;; Shoot complete row and any flavour of column
    (:action shoot-row-and-column
            ;; ?r - what complete row we are shooting.
            ;; ?t - At which row we are stopping on the column that we are "eating"
            ;; ?c - the colour of the range
            :parameters (?r - number ?t - number ?c - colour)
            :precondition
                (and
                    ;; rows of the shot are coherent
                    (gt ?t ?r)

                    ;; stop possible weird stuff
                    (not (= ?c null))
                    (not (= ?c wildcard))
                    ;; colour block and hand is the same (we avoid null movements)
                    (or (hand ?c) (hand wildcard))

                    ;; all the blocks in the row and in the corresponding part of the
                    ;; column are either the same colour or are empty
                    (forall (?row ?col - number) 
                        (and
                            (imply
                                (= ?r ?row)
                                (or
                                    (coloured ?r ?col ?c)
                                    (coloured ?r ?col null)))
                            (imply
                                (and
                                    (gt ?row ?r)
                                    (not (gt ?row ?t))
                                    (islastcolumn ?col))
                                (or
                                    (coloured ?row ?col ?c)
                                    (coloured ?row ?col null)))))

                    ;; we have to eat at least one of those!
                    (exists (?row ?col - number) 
                        (or 
                            (and
                                (= ?r ?row)
                                (coloured ?r ?col ?c))
                        
                            (and
                                (gt ?row ?r)
                                (not (gt ?row ?t))
                                (islastcolumn ?col)
                                (coloured ?row ?col ?c))))
                            
                    ;; either ?t is the last row, or in its successor there is a different colour
                    (or
                        (isbottomrow ?t)
                        (exists (?nextrow ?lastcol - number)
                            (and
                                (succ ?nextrow ?t)
                                (islastcolumn ?lastcol)
                                (not (coloured ?nextrow ?lastcol ?c))
                                (not (coloured ?nextrow ?lastcol null))))))
            :effect
                (and
                    ;; move everything downwards except the last column.
                    ;; 2 cases: we are on the top row or  we are on a middle row
                    (forall (?currentrow ?currentcol ?nextrow - number)
                        (and
                            ;; case 1 - We are on the top row: we must restore the "null" colour
                            (when
                                (istoprow ?currentrow)
                                (and
                                    (not (coloured ?currentrow ?currentcol ?c))
                                    (coloured ?currentrow ?currentcol null)))

                            ;; case 2 - We are on the middle row: disable the current colour and change the next colour
                            (forall (?currentcolor ?nextcolor - colour)
                                (when
                                    (and
                                        (not (istoprow ?nextrow))        ;; is not top row
                                        (not (islastcolumn ?currentcol)) ;; is not last column
                                        ;; position the "pointers"
                                        (lt ?currentrow ?r)              
                                        (succ ?nextrow ?currentrow)
                                        ;; ensure that the cells have the pertaining colours
                                        (coloured ?currentrow ?currentcol ?currentcolor)
                                        (coloured ?nextrow ?currentcol ?nextcolor)
                                        ;;avoid effect contradiction (if both colours are equal)
                                        (not (= ?currentcolor ?nextcolor))
                                    )
                                    (and ;; and as an effect we change the lower row
                                        (not (coloured ?nextrow ?currentcol ?nextcolor))
                                        (coloured ?nextrow ?currentcol ?currentcolor))))))

                    ;; The waterfall effect
                    (forall (?currentrow ?nextrow ?lastcolumn ?d ?dplus1 ?d2 - number ?nextcolour ?currentcolour - colour)
                        (and

                            ;; unconditionally, if we reach the end of any row at all, the cell
                            ;; on the top right of the grid will get a null.
                            (when
                                (and
                                    (istoprow ?currentrow)
                                    (islastcolumn ?lastcolumn)
                                    (coloured ?currentrow ?lastcolumn ?nextcolour)
                                    (not (coloured ?currentrow ?lastcolumn null)))
                                (and
                                    (not (coloured ?currentrow ?lastcolumn ?nextcolour))
                                    (coloured ?currentrow ?lastcolumn null)))

                   
                            ;; we act only on the set of cells between ?r and ?t
                            ;; base case: we are on top of the row
                            (when 
                                (and
                                    ;; we consider the case of the last column
                                    (islastcolumn ?lastcolumn)
                                    ;; distance between the row we shoot at and where we stop is ?d
                                    (distance ?r ?t ?d)
                                    ;; and we calculate the distance we have to move cells downwards
                                    (succ ?dplus1 ?d)
                                    ;; we need to fix this here to be able to compute the distance with the
                                    ;; nextrow pointer, which is the one we use to change 
                                    (istoprow ?currentrow)
                                    ;; we are on top of the ?t
                                    (or (lt ?nextrow ?t) (= ?nextrow ?t))
                                    ;; ?d2 is the distance between nextrow currentrow
                                    ;; and this distance is less than what we should copy
                                    (distance ?currentrow ?nextrow ?d2)
                                    (lt ?d2 ?dplus1)

                                    ;; and the colours are correct and not null
                                    (coloured ?nextrow ?lastcolumn ?nextcolour)
                                    (not (= ?nextcolour null)))
                                (and ;; we switch colours
                                    (not (coloured ?nextrow ?lastcolumn ?nextcolour))
                                    (coloured ?nextrow ?lastcolumn null)))
                            ;; other cases
                            (when 
                                (and
                                     ;; we consider the case of the last column
                                    (islastcolumn ?lastcolumn)
                                    ;; distance between the row we shoot at and where we stop is ?d
                                    (distance ?r ?t ?d)
                                    ;; and we calculate the distance we have to move cells downwards
                                    (succ ?dplus1 ?d)
                                    ;; we are on top of the ?t
                                    (or (lt ?nextrow ?t) (= ?nextrow ?t))
                                    ;; and the distance is ?dplus1
                                    (distance ?nextrow ?currentrow ?dplus1)
                                    ;; and the colours are correct and different
                                    (coloured ?currentrow ?lastcolumn ?currentcolour)
                                    (coloured ?nextrow ?lastcolumn ?nextcolour)
                                    (not (= ?currentcolour ?nextcolour)))
                                (and ;; we switch colours
                                    (not (coloured ?nextrow ?lastcolumn ?nextcolour))
                                    (coloured ?nextrow ?lastcolumn ?currentcolour)))
                            ;; finally, we change the colour of the cell on the bottom of the ?t.
                            (when 
                                (and
                                     ;; we consider the case of the last column
                                    (islastcolumn ?lastcolumn)
                                    ;; distance between the row we shoot at and where we stop is ?d
                                    (distance ?r ?t ?d)
                                    ;; and we calculate the distance we have to move cells downwards
                                    (succ ?dplus1 ?d)
                                    (succ ?nextrow ?t)
                                    ;; and the colour is correct and different from null
                                    (coloured ?nextrow ?lastcolumn ?nextcolour))
                                (and ;; we switch colours
                                    (not (coloured ?nextrow ?lastcolumn ?nextcolour))
                                    (coloured ?nextrow ?lastcolumn ?c)))))
                   
                   ;; Change hands colour:
                   ;; base case when we eat all the last column or is all null
                   (when 
                        (isbottomrow ?t)
                        (and 
                            (hand ?c)
                            (not (hand wildcard))))

                    ;; - we are not the last row before ground, therefore
                    ;; the colour of the hand becomes the one under the last cell of the row
                    (forall (?nextrow ?lastcol - number ?nextcolour - colour)
                        (and 
                            (when 
                                (and
                                    ;; there is another row down this one
                                    (succ ?nextrow ?t)
                                    ;; and we are on the last column
                                    (islastcolumn ?lastcol)
                                    ;; and the next (down) cell is coloured ?nextcolour
                                    (coloured ?nextrow ?lastcol ?nextcolour))
                                (and
                                    ;; we change the colour of the next (down) cell
                                    (not (coloured ?nextrow ?lastcol ?nextcolour))
                                    (coloured ?nextrow ?lastcol ?c)
                                    ;; we set the hand to the next cell colour
                                    (hand ?nextcolour)
                                    (not (hand ?c))
                                    ;; we ensure we lose the wildcard if we had it
                                    (not (hand wildcard))))))))


;; Shoot complete row and 0 rows down
    (:action shoot-only-full-row
            ;; ?r - what complete row we are shooting.
            ;; ?c - the colour of the range
            :parameters (?r - number ?c - colour)
            :precondition
                (and
                    ;; stop possible weird stuff
                    (not (= ?c null))
                    (not (= ?c wildcard))
                    ;; colour block and hand is the same (we avoid null movements)
                    (or (hand ?c) (hand wildcard))

                    ;; all the blocks in the row and in the corresponding part of the
                    ;; column are either the same colour or are empty
                    (forall (?col - number) 
                        (or
                            (coloured ?r ?col ?c)
                            (coloured ?r ?col null)))

                    ;; we have to eat at least one of those!
                    (exists (?col - number) 
                        (coloured ?r ?col ?c))
                            
                    ;; either ?r is the last row, or in the cell below the last one 
                    ;; we have a different colour than ?c
                    (or
                        (isbottomrow ?r)
                        (exists (?nextrow ?lastcol - number)
                            (and
                                (succ ?nextrow ?r)
                                (islastcolumn ?lastcol)
                                (not (coloured ?nextrow ?lastcol ?c))
                                (not (coloured ?nextrow ?lastcol null))))))
            :effect
                (and
                    ;; move everything downwards
                    ;; 2 cases: we are on the top row or  we are on a middle row
                    (forall (?currentrow ?currentcol ?nextrow - number)
                        (and
                            ;; case 1 - We are on the top row: we must restore the "null" colour
                            (when
                                (istoprow ?currentrow)
                                (and
                                    (not (coloured ?currentrow ?currentcol ?c))
                                    (coloured ?currentrow ?currentcol null)))

                            ;; case 2 - We are on the middle row: disable the current colour and change the next colour
                            (forall (?currentcolor ?nextcolor - colour)
                                (when
                                    (and
                                        (not (istoprow ?nextrow))        ;; is not top row
                                        ;; position the "pointers"
                                        (lt ?currentrow ?r)              
                                        (succ ?nextrow ?currentrow)
                                        ;; ensure that the cells have the pertaining colours
                                        (coloured ?currentrow ?currentcol ?currentcolor)
                                        (coloured ?nextrow ?currentcol ?nextcolor)
                                        ;;avoid effect contradiction (if both colours are equal)
                                        (not (= ?currentcolor ?nextcolor))
                                    )
                                    (and ;; and as an effect we change the lower row
                                        (not (coloured ?nextrow ?currentcol ?nextcolor))
                                        (coloured ?nextrow ?currentcol ?currentcolor))))))

                   ;; Change hands colour:
                   ;; base case when we eat all the last column or is all null
                   (when 
                        (isbottomrow ?r)
                        (and 
                            (hand ?c)
                            (not (hand wildcard))))

                    ;; - we are not the last row before ground, therefore
                    ;; the colour of the hand becomes the one under the last cell of the row
                    (forall (?nextrow ?lastcol - number ?nextcolour - colour)
                        (and 
                            (when 
                                (and
                                    ;; there is another row down this one
                                    (succ ?nextrow ?r)
                                    ;; and we are on the last column
                                    (islastcolumn ?lastcol)
                                    ;; and the next (down) cell is coloured ?nextcolour
                                    (coloured ?nextrow ?lastcol ?nextcolour))
                                (and
                                    ;; we change the colour of the next (down) cell
                                    (not (coloured ?nextrow ?lastcol ?nextcolour))
                                    (coloured ?nextrow ?lastcol ?c)
                                    ;; we set the hand to the next cell colour
                                    (hand ?nextcolour)
                                    (not (hand ?c))
                                    ;; we ensure we lose the wildcard if we had it
                                    (not (hand wildcard))))))))
)