Search code examples
clipsexpert-system

Can I compare existing fact values to random numbers on the RHS of a defrule?


I am working on a Dots-and-Boxes game and the code I have thus far is:

(deffacts Game_Start "Sets turn number to 1 and next turn to player"
    (turn_num 1)
    (next_turn p)
    (Line_Taken 0))

(defrule First_Three_Moves "Used for the first 3 moves of the game"
    ?f <-(turn_num ?t_num)
    (next_turn p)
    (or(turn_num 1)
       (turn_num 2)
       (turn_num 3))
    =>
    (bind ?move (random 1 24))
    (bind ?tn (+ ?t_num 1))
    (assert (turn_num ?tn))
    (retract ?f)
    (assert(Line_Taken ?move))
    (printout t "Take line #" ?move crlf)
    (assert (next_turn c))))

(defrule Computer_Move
    ?turn <- (next_turn c)
    =>
    (printout t "Enter computer move: ")
    (bind ?c_move (read))
    (assert(Line_Taken ?c_move))
    (retract ?turn)
    (assert (next_turn p)))

I get a random number between 1 and 24 for my first three moves. Is there a way to make sure that I haven't already selected a move number on the RHS after I do (bind ?move (random 1 24)) ?


Solution

  • You can use the fact query functions on the RHS to determine if a fact exists for a specific move:

    (defrule First_Three_Moves "Used for the first 3 moves of the game"
        ?f <-(turn_num ?t_num)
        (next_turn p)
        (or(turn_num 1)
           (turn_num 2)
           (turn_num 3))
        =>
        (bind ?move (random 1 24))
        (while (any-factp ((?lt Line_Taken)) (member$ ?move ?lt:implied))
           (bind ?move (random 1 24)))
        (bind ?tn (+ ?t_num 1))
        (assert (turn_num ?tn))
        (retract ?f)
        (assert(Line_Taken ?move))
        (printout t "Take line #" ?move crlf)
        (assert (next_turn c)))