I am working on a program that will tell me which moves to make in a dots-and-boxes game. I am trying to implement a defrule
that will check to see if a box already has 2
of the possible 4
sides taken. If this is the case then I don't want to take one of the remaining two lines, as that will give the opponent a free point.
(defrule Player_Move_No_Box_1_1
(next_turn p)
(turn_num ?t_num)
(test(> ?t_num 3))
(line ?l1&~1)
(not(line 1))
=>
(if
(not(or(and(any-factp ((?l line)) (member$ (+ ?l1 3) ?l:implied))(any-factp ((?l line)) (member$ (+ ?l1 4) ?l:implied)))
(and(any-factp ((?l line)) (member$ (+ ?l1 3) ?l:implied))(any-factp ((?l line)) (member$ (+ ?l1 7) ?l:implied)))
(and(any-factp ((?l line)) (member$ (+ ?l1 4) ?l:implied))(any-factp ((?l line)) (member$ (+ ?l1 7) ?l:implied)))))
then
(printout t "Take line #1" crlf)
(assert(line 1))
(assert(next_turn c))))
I've been trying a lot of different things, but this is the last code I tried to use, but with no success. For this piece of code I'm looking at line 1
(clockwise starting from the top of a box the boxes are numbered: x
, x+4
, x+7
, x+3
). Is there a simpler way of making this check, or will this way work and I've just messed the code up somewhere?
I would suggest explicitly representing each possible line as a fact and denote in the fact whether the line has been taken. Also do the pattern matching in the conditions of the rules rather than the actions.
I've stripped out the turn information from your original rule just to make it easier to test it.