....
%%%%%%%%%%%%%%%%%%%%%%%%%%%%validmove(Plyr,State,Proposed)%%%%%%%%%%%%%%%%%%%%
%%
%% define validmove(Plyr,State,Proposed).
% - true if Proposed move by Plyr is valid at State.
% holds if the Proposed position is empty ('.'), and
% if in any of the 8 directions
% there is a sequence of other player's stones
% followed by this player's stone without empty spaces
%
%north
validmove(Plyr,State,Proposed) :-
get(State,Proposed,.),
northLine(State,Plyr,Proposed,Line),
last(Line,LastPoint),
north(LastPoint,AfterLastPoint),
get(State,AfterLastPoint,Plyr).
%south
validmove(Plyr,State,Proposed) :-
get(State,Proposed,.),
southLine(State,Plyr,Proposed,Line),
last(Line,LastPoint),
south(LastPoint,AfterLastPoint),
get(State,AfterLastPoint,Plyr).
%west
validmove(Plyr,State,Proposed) :-
get(State,Proposed,.),
westLine(State,Plyr,Proposed,Line),
last(Line,LastPoint),
west(LastPoint,AfterLastPoint),
get(State,AfterLastPoint,Plyr).
%east
validmove(Plyr,State,Proposed) :-
get(State,Proposed,.),
eastLine(State,Plyr,Proposed,Line),
last(Line,LastPoint),
east(LastPoint,AfterLastPoint),
get(State,AfterLastPoint,Plyr).
%northWest
validmove(Plyr,State,Proposed) :-
get(State,Proposed,.),
northWestLine(State,Plyr,Proposed,Line),
last(Line,LastPoint),
northWest(LastPoint,AfterLastPoint),
get(State,AfterLastPoint,Plyr).
%northEast
validmove(Plyr,State,Proposed) :-
get(State,Proposed,.),
northEastLine(State,Plyr,Proposed,Line),
last(Line,LastPoint),
northEast(LastPoint,AfterLastPoint),
get(State,AfterLastPoint,Plyr).
%southWest
validmove(Plyr,State,Proposed) :-
get(State,Proposed,.),
southWestLine(State,Plyr,Proposed,Line),
last(Line,LastPoint),
southWest(LastPoint,AfterLastPoint),
get(State,AfterLastPoint,Plyr).
%southEast
validmove(Plyr,State,Proposed) :-
get(State,Proposed,.),
southEastLine(State,Plyr,Proposed,Line),
last(Line,LastPoint),
southEast(LastPoint,AfterLastPoint),
get(State,AfterLastPoint,Plyr).
....
% predicates that return adjacent positions along 4 major directions
% and 4 minor, diagonal, directions
%
% major directions
% north(Pos,NorthOfPos)
north([X,Y], [X, YN]) :- YN is Y - 1.
% south(Pos,SouthOfPos)
south([X,Y], [X, YS]) :- YS is Y + 1.
% west(Pos,WestOfPos)
west([X,Y], [XW, Y]) :- XW is X - 1.
% east(Pos,WestOfPos)
east([X,Y], [XW, Y]) :- XW is X + 1.
% minor, diagonal, directions are obtained from the major predicates
% using DCG expansion
% northEast(Pos,NorthEastOfPos)
northEast --> north,east.
% northWest(Pos,NorthWestOfPos)
northWest --> north,west.
% southEast(Pos,SouthEastOfPos)
southEast --> south,east.
% southWest(Pos,SouthWestOfPos)
southWest --> south,west.
% +---------------list of lines-----------------------------------------------+
% | +-------line of positions--------+ |
% | | position | |
% [ [ [X1, Y1], [X2,Y2], [X3,Y3], ...], [[X4, Y4], [X5,Y5], [X6,Y6], ...], ...]
% find a line of positions with other player's stones
% followed by this player's stones in the North direction
% from the given position
% do not check the state of the given position
% (it can be empty, or contain either player's stones)
%
% return a line of consecutive other player's stones
% in the 8 directions
%
% example:
% given
% S = ([[.,.,.,.,.,.],
% [.,.,.,.,.,.],
% [.,.,2,1,.,.],
% [.,.,1,2,.,.],
% [.,.,.,2,.,.],
% [.,.,.,x,.,.] ]).
%
% x is at [3,5]
%
% northLine(S,1,[3,5],[[3,4],[3,3]]) holds
%
% logic:
% if get holds on the adjacent position
% and contents are other player's stone
% add this position to the list,
% otherwise return an empty list
northLine(State,Plyr,Pos,LineOfPositions) :-
otherPlyr(Plyr,OtherPlyr),
north(Pos,NextPos),
( get(State,NextPos,OtherPlyr)
-> northLine(State,Plyr,NextPos,FollowingPositions),
LineOfPositions = [NextPos|FollowingPositions]
; LineOfPositions = []
).
% the following prediates are the same as above except in a different
% direction
southLine(State,Plyr,Pos,LineOfPositions) :-
otherPlyr(Plyr,OtherPlyr),
south(Pos,NextPos),
( get(State,NextPos,OtherPlyr)
-> southLine(State,Plyr,NextPos,FollowingPositions),
LineOfPositions = [NextPos|FollowingPositions]
; LineOfPositions = []
).
westLine(State,Plyr,Pos,LineOfPositions) :-
otherPlyr(Plyr,OtherPlyr),
west(Pos,NextPos),
( get(State,NextPos,OtherPlyr)
-> westLine(State,Plyr,NextPos,FollowingPositions),
LineOfPositions = [NextPos|FollowingPositions]
; LineOfPositions = []
).
eastLine(State,Plyr,Pos,LineOfPositions) :-
otherPlyr(Plyr,OtherPlyr),
east(Pos,NextPos),
( get(State,NextPos,OtherPlyr)
-> eastLine(State,Plyr,NextPos,FollowingPositions),
LineOfPositions = [NextPos|FollowingPositions]
; LineOfPositions = []
).
northWestLine(State,Plyr,Pos,LineOfPositions) :-
otherPlyr(Plyr,OtherPlyr),
northWest(Pos,NextPos),
( get(State,NextPos,OtherPlyr)
-> northWestLine(State,Plyr,NextPos,FollowingPositions),
LineOfPositions = [NextPos|FollowingPositions]
; LineOfPositions = []
).
northEastLine(State,Plyr,Pos,LineOfPositions) :-
otherPlyr(Plyr,OtherPlyr),
northEast(Pos,NextPos),
( get(State,NextPos,OtherPlyr)
-> northEastLine(State,Plyr,NextPos,FollowingPositions),
LineOfPositions = [NextPos|FollowingPositions]
; LineOfPositions = []
).
southWestLine(State,Plyr,Pos,LineOfPositions) :-
otherPlyr(Plyr,OtherPlyr),
southWest(Pos,NextPos),
( get(State,NextPos,OtherPlyr)
-> southWestLine(State,Plyr,NextPos,FollowingPositions),
LineOfPositions = [NextPos|FollowingPositions]
; LineOfPositions = []
).
southEastLine(State,Plyr,Pos,LineOfPositions) :-
otherPlyr(Plyr,OtherPlyr),
southEast(Pos,NextPos),
( get(State,NextPos,OtherPlyr)
-> southEastLine(State,Plyr,NextPos,FollowingPositions),
LineOfPositions = [NextPos|FollowingPositions]
; LineOfPositions = []
).