I once wrote a door riddle solver in SWI-Prolog. I only tried it on the eight gates of Bill and some riddles in Witherwood Castle but it worked for these.
×/*
List doors with their initial state and orbs with their functions.
o must contain all doors which get opened by the orb.
c must contain all doors which get closed by the orb.
t must contain all doors which get toggled by the orb.
door(1,c).
door(2,o).
door(3,c).
orb(1,[t([1,2])]).
orb(2,[c([2,3])]).
orb(3,[o([3])]).
*/
% 8 Gates Of Bill
door(1,c).
door(2,c).
door(3,c).
door(4,c).
door(5,c).
door(6,c).
door(7,c).
door(8,c).
orb(1,[o([3]),c([5]),t([1])]).
orb(2,[o([3,7]),c([4])]).
orb(3,[o([8]),c([7]),t([3])]).
orb(4,[o([1]),c([3]),t([5])]).
orb(5,[o([4]),c([1])]).
orb(6,[o([3,6]),c([5]),t([2])]).
orb(7,[t([4,5])]).
orb(8,[o([3]),c([7])]).
orb(9,[c([8])]).
% Solution
solvePuzzle(Solution) :- listDoors(Doors), allOpen(Doors,OpenDoors), (getNum(Max), doorriddle(Doors,OpenDoors,Solution,0,Max)).
getNum(1).
getNum(X) :- getNum(A), X is A+1.
listDoors(List) :- findall((X,Y),door(X,Y),List).
allOpen([],[]).
allOpen([(Number,_)|Rest],[(Number,o)|OpenRest]) :- allOpen(Rest,OpenRest).
doorriddle(WantedDoors,WantedDoors,[],_,_).
doorriddle(Doors,WantedDoors,[X|Solution],Step,Max) :- Step < Max, orb(X,Functions), useFunctions(Functions,Doors,ChangedDoors), NextStep is Step +1, doorriddle(ChangedDoors,WantedDoors,Solution,NextStep,Max).
useFunctions([],Doors,Doors).
useFunctions([Function1|Functions],Doors,ResultDoors) :- useFunctions(Functions,Doors,ChangedDoors), useFunction(Function1,ChangedDoors,ResultDoors).
useFunction(t(List),Doors,ChangedDoors) :- toggleList(List,Doors,ChangedDoors).
useFunction(o(List),Doors,ChangedDoors) :- openList(List,Doors,ChangedDoors).
useFunction(c(List),Doors,ChangedDoors) :- closeList(List,Doors,ChangedDoors).
toggleList([],Doors,Doors).
toggleList([Num|Rest],[(Num,State)|Doors],[(Num,ToggleState)|ChangedDoors]) :- toggle(State,ToggleState), toggleList(Rest,Doors,ChangedDoors).
toggleList([X|Rest],[(Num,State)|Doors],[(Num,State)|ChangedDoors]) :- X \= Num, toggleList([X|Rest],Doors,ChangedDoors).
openList([],Doors,Doors).
openList([Num|Rest],[(Num,_)|Doors],[(Num,o)|ChangedDoors]) :- openList(Rest,Doors,ChangedDoors).
openList([X|Rest],[(Num,State)|Doors],[(Num,State)|ChangedDoors]) :- X \= Num, openList([X|Rest],Doors,ChangedDoors).
closeList([],Doors,Doors).
closeList([Num|Rest],[(Num,_)|Doors],[(Num,c)|ChangedDoors]) :- closeList(Rest,Doors,ChangedDoors).
closeList([X|Rest],[(Num,State)|Doors],[(Num,State)|ChangedDoors]) :- X \= Num, closeList([X|Rest],Doors,ChangedDoors).
toggle(o,c).
toggle(c,o).
Getting solutions is done by consulting the file in SWI-Prolog and then entering
More answers arrive by pressing ; (semicolon).