Tiles source
The ProscriptLS source used in the Likes example. Links to these source files are: tiles.pl . This program uses the object.pl, listut2.pl, dom.pl, and data_predicates.pl library files.
tiles.pl
:- module(tiles, [select_test/0, save_tiles/0, load_tiles/0]).
:- use_module('../library/object'). % for >>/2.
:- use_module('../library/data_predicates').
:- ensure_loaded('../library/listut2'). % for append_lists/2
:- ensure_loaded('../library/dom'). % for dom_page_offset/2
:- dynamic(is_selected/1).
% For tiles the shadow tile structure functor is 'ts'
% and the arguments are 'x', 'y', etc.
% For the game the shadow game structure functor is 'g'
% and the arguments are 'board_left', 'turn', etc.
% (Note that there is currently only one 'game' so the ID is always '1'.)
:- initialization(init).
init :-
data_predicate_dynamics([
data_predicates(g, game,[tile_size, board_left, board_top, board_width, board_height, board_translate, turn, replacements]), % e.g. game_board_left(ID, X)...
data_predicates(ts, tile,[x, y,bx,by,size,colors,container]), % e.g. tile_x(ID, X), tile_y(ID, Y)...
data_predicates(lp, legal_position, [bx, by])
]).
select_test :-
_Canvas >> [id -:> canvas,
getContext('2d') *:> Ctx,
width +:> W,
height +:> H,
@ dom_page_offset(PTop, PLeft),
addEventListener(click, [object-E]^select(E, PTop, PLeft))],
assert_data(g(50, 10, 10, 800, 800, 1>1, 1, []), 1),
initial_hands_expanded(2, Hands),
setup_hands(Hands, TileIDs),
draw_all_tiles(TileIDs, Ctx, W, H).
save_tiles :-
new_memory_file(DataMemFile),
open_memory_file(DataMemFile, write, Stream),
save_data_stream(game, Stream),
save_data_stream(tile, Stream),
save_data_stream(legal_position, Stream),
close(Stream),
copy_memory_file_to_local_storage(DataMemFile, save_tiles),
free_memory_file(DataMemFile).
load_tiles :-
retract_all_data(game),
retract_all_data(tile),
retract_all_data(legal_position),
copy_local_storage_to_memory_file(save_tiles, DataMemFile),
wam_compiler:compile_and_free_memory_file(DataMemFile).
dummy_reference :-
dummy_reference,
select(_,_,_), % referenced indirectly in addEventListener/3 call.
% following are generated by data_predicate_dynamics/1.
tile_x(_),
tile_y(_),
tile_bx(_),
tile_by(_),
tile_size(_),
tile_colors(_),
tile_container(_),
legal_position_bx(_),
legal_position_by(_).
% clientX and clientY are coordinates within the containing HTMLCanvasElement
% It appears that the rendering coordinates (e.g. moveTo(RX, RY)) are coordinates
% within the containing HTMLCanvasElement minus the canvas offset.
% RX = clientX - offsetX.
select(Event, PTop, PLeft) :-
Event >> [pageX +:> PageX, pageY +:> PageY],
dom_release_object(Event),
X is PageX - PLeft,
Y is PageY - PTop,
% writeln(select(PageX, PageY, PLeft, PTop, X, Y)),
(point_in_tile(ID, X, Y)
-> on_click_tile(ID, X, Y) % at most one tile contains (X, Y).
;
legal_position_bx(ID, BX),
legal_position_by(ID, BY),
point_in_board_position(BX, BY, X, Y)
-> true
;
true
).
point_in_tile(ID, MX, MY) :-
tile_x(ID, TX),
tile_y(ID, TY),
tile_size(ID, Size),
in_square(MX, MY, TX, TY, Size).
in_square(X, Y, Left, Top, Size) :-
in_interval(X, Left, Left+Size),
in_interval(Y, Top, Top+Size).
in_interval(V, Low, High) :-
V >= Low,
V =< High.
point_in_board_position(BX, BY, X, Y) :-
game_tile_size(Size),
board_position_top_left_coordinates(BX, BY, BCX, BCY),
in_square(X, Y, BCX, BCY, Size).
board_position_top_left_coordinates(GridX, GridY, X, Y) :-
game_tile_size(TileSize),
game_board_left(BoardLeft),
game_board_width(BoardWidth),
game_board_top(BoardTop),
game_board_height(BoardHeight),
game_board_translate(TranslateX > TranslateY),
X is BoardLeft + TranslateX + BoardWidth / 2 + (GridX - 0.5) * TileSize,
Y is BoardTop + TranslateY + BoardHeight / 2 + (GridY - 0.5) * TileSize.
on_click_tile(ID, _X, _Y) :-
%writeln(click(ID, X, Y)),
(tile_in_active_hand(ID)
-> on_click_active_hand_tile(ID)
;
true % writeln(not_active)
).
on_click_active_hand_tile(ID) :-
_ >> [id -:> canvas, getContext('2d') *:> Ctx],
(retract(is_selected(OldID))
-> draw_all_tile(OldID, Ctx) % de-select OldID
;
true
),
asserta(is_selected(ID)),
yield,
draw_all_tile(ID, Ctx).
setup_hands([], []).
setup_hands([_+HandTiles|T], IDs) :-
setup_hand(HandTiles, IDs, IDTail),
setup_hands(T, IDTail).
setup_hand([], Tail, Tail).
setup_hand([H-ID|T], [ID|OtherIDs], IDTail) :-
assert_data(H, ID),
setup_hand(T, OtherIDs, IDTail).
hand_origin(1).
initial_hands_expanded(NumberOfPlayers, ExpandedHands) :-
initial_hands(NumberOfPlayers, Hands),
expand_hands(Hands, ExpandedHands).
expand_hands([], []).
expand_hands([H|T], [EH|ET]) :-
expand_hand(H, EH),
expand_hands(T, ET).
expand_hand(ID+BriefTiles, ID+ExpandedTiles) :-
game_tile_size(Size),
expand_brief_tiles(BriefTiles, ID, Size, ExpandedTiles).
expand_brief_tiles([], _, _, []).
expand_brief_tiles([H|T], HandID, Size, [EH|ET]) :-
expand_brief_tile(H, HandID, Size, EH),
expand_brief_tiles(T, HandID, Size, ET).
% [x, y,bx,by,size,colors,container]
expand_brief_tile(t(BoardX, BoardY, AbstractColors, TileID),
HandID,
Size,
ts(X, Y, BoardX, BoardY, Size, Colors, container(HandID, hand))-TileID) :-
X is BoardX * Size,
Y is BoardY * Size,
abstract_colors(AbstractColors, Colors).
abstract_colors([], []).
abstract_colors([AH|AT], [CH|CT]) :-
abstract_color(AH, CH),
abstract_colors(AT, CT).
abstract_color(a, red).
abstract_color(b, green).
abstract_color(c, blue).
abstract_color(d, yellow).
initial_hands(2, [1+Player1Tiles, 2+Player2Tiles]) :-
Col1 is 1,
Col2 is Col1 + 1,
hand_origin(Origin1),
Player1Row1 is Origin1,
Player1Row2 is Origin1 + 1,
Player1Row3 is Origin1 + 2,
Player1Row4 is Origin1 + 3,
Origin2 is Origin1 + 5,
Player2Row1 is Origin2,
Player2Row2 is Origin2 + 1,
Player2Row3 is Origin2 + 2,
Player2Row4 is Origin2 + 3,
Player1Tiles = [ t(Col1, Player1Row1,[a,a,a,a], t01),
t(Col1, Player1Row2,[b,a,a,a], t02),
t(Col1, Player1Row3,[b,b,a,a], t03),
t(Col1, Player1Row4,[b,a,b,a], t04),
t(Col2, Player1Row1,[a,a,a,a], t05),
t(Col2, Player1Row2,[b,a,a,a], t06),
t(Col2, Player1Row3,[b,b,a,a], t07),
t(Col2, Player1Row4,[b,a,b,a], t08)
],
Player2Tiles = [t(Col1, Player2Row1,[b,b,b,b], t09),
t(Col1, Player2Row2,[a,b,b,b], t10),
t(Col1, Player2Row3,[a,a,b,b], t11),
t(Col1, Player2Row4,[a,b,a,b], t12),
t(Col2, Player2Row1,[b,b,b,b], t13),
t(Col2, Player2Row2,[a,b,b,b], t14),
t(Col2, Player2Row3,[a,a,b,b], t15),
t(Col2, Player2Row4,[a,b,a,b], t16)
].
% (X > Y) is a point (X,Y).
% Web API method arguments of type number or integer accept arithmetic
% expressions; e.g. (1 + 0.5 * 50).
draw_tile(Ctx, Tile) :-
tile_x(Tile, X),
tile_y(Tile, Y),
tile_size(Tile, Size),
Corners = [X > Y,X + Size > Y,X + Size > Y + Size, X > Y + Size],
Center = (X + 0.5 * Size > Y + 0.5 * Size),
tile_colors(Tile, Colors),
draw_triangles(Corners, Colors, Center, Ctx),
tile_bx(Tile, BX),
tile_by(Tile, BY),
tile_label(BX, BY, Text),
Ctx >> [
save,
fillStyle <:+ '#000',
fillText(Text, X+5, Y+10),
restore
].
draw_triangles([P1, P2|OtherCorners], [Color1|OtherColors], Center, Ctx) :-
draw_triangle(P1, P2, Color1, Center, Ctx),
draw_triangles1([P2|OtherCorners], OtherColors, P1, Center, Ctx).
draw_triangles1([P1], [Color], P2, Center, Ctx) :-
draw_triangle(P1, P2, Color, Center, Ctx).
draw_triangles1([P1, P2|OtherCorners], [Color1|OtherColors], FirstP, Center, Ctx) :-
draw_triangle(P1, P2, Color1, Center, Ctx),
draw_triangles1([P2|OtherCorners], OtherColors, FirstP, Center, Ctx).
draw_triangle(P1x > P1y, P2x > P2y, Color, CenterX > CenterY, Ctx) :-
Ctx >> [
beginPath,
moveTo(P1x, P1y),
lineTo(P2x, P2y),
lineTo(CenterX, CenterY),
closePath,
save,
fillStyle <:+ Color,
fill,
stroke,
restore
].
draw_all_tiles(AllTiles, Ctx, CW, CH) :-
center_board,
Ctx >> [
fillStyle <:+ '#999',
fillRect(0, 0, CW, CH)
],
draw_all_tiles1(AllTiles, Ctx).
draw_all_tiles1([], _).
draw_all_tiles1([H|T], Ctx) :-
draw_all_tile(H, Ctx),
draw_all_tiles1(T, Ctx).
draw_all_tile(Tile, Ctx) :-
(tile_in_inactive_hand(Tile) -> GlobalAlpha = 0.3; GlobalAlpha = 1),
Ctx >> [
save,
globalAlpha <:+ GlobalAlpha
],
draw_tile(Ctx, Tile),
Ctx >*> restore,
(is_selected(Tile)
-> draw_selected_tile_mark(Tile, Ctx)
;
true
),
draw_replacements(Tile, Ctx).
draw_replacements(Tile, Ctx) :-
(game_replacements(Rs),
member(Tile, Rs)
-> draw_replacement_tile_mark(Tile, Ctx)
;
true
).
center_board.
draw_selected_tile_mark(Tile, Ctx) :-
tile_x(Tile, X),
tile_y(Tile, Y),
tile_size(Tile, Size),
MidX is X + (Size / 2),
MidY is Y + (Size / 2),
Adjust is Size / 4,
VerticalTopX = MidX,
VerticalTopY is MidY - Adjust,
VerticalBottomX = MidX,
VerticalBottomY is MidY + Adjust,
HorizontalLeftX is MidX-Adjust,
HorizontalLeftY = MidY,
HorizontalRightX is MidX+Adjust,
HorizontalRightY = MidY,
game_turn(GT),
highlight_color(GT, Color),
Ctx >> [
save,
lineWidth <:+ 3,
strokeStyle <:+ Color,
beginPath,
moveTo(VerticalTopX, VerticalTopY),
lineTo(VerticalBottomX, VerticalBottomY),
closePath,
stroke,
beginPath,
moveTo(HorizontalLeftX, HorizontalLeftY),
lineTo(HorizontalRightX, HorizontalRightY),
closePath,
stroke,
restore
].
draw_replacement_tile_mark(Tile, Ctx) :-
tile_x(Tile, X),
tile_y(Tile, Y),
tile_size(Tile, Size),
MidX is X + (Size / 2),
MidY is Y + (Size / 2),
Adjust is Size / 4,
game_turn(GT),
highlight_color(GT, Color),
Ctx >> [
save,
lineWidth <:+ 3,
strokeStyle <:+ Color,
beginPath,
arc(MidX, MidY, Adjust, 0, 2*pi),
closePath,
stroke,
restore
].
container_id(container(ID, _Type), ID).
container_type(container(_ID, Type), Type).
tile_label(BoardX, BoardY, Text) :-
number_codes(BoardX, BXCodes),
number_codes(BoardY, BYCodes),
append_lists(["x", BXCodes, "y", BYCodes], TextCodes),
atom_codes(Text, TextCodes).
tile_in_inactive_hand(Tile) :-
tile_container(Tile, Container),
container_type(Container, hand),
game_turn(TurnID),
\+ container_id(Container, TurnID).
tile_in_active_hand(Tile) :-
tile_container(Tile, Container),
container_type(Container, hand),
game_turn(TurnID),
container_id(Container, TurnID).
highlight_color(1, '#CCFFCC').
highlight_color(2, '#CCCCFF').