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(PTopPLeft),
        addEventListener(click, [object-E]^select(EPTopPLeft))],

    assert_data(g(50, 10, 10, 800, 800, 1>1, 1, []), 1),
    initial_hands_expanded(2, Hands),
    setup_hands(HandsTileIDs),
    draw_all_tiles(TileIDsCtxWH).

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(EventPTopPLeft:-
    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(IDXY)
      -> on_click_tile(IDXY)  % at most one tile contains (X, Y).
    ;
     legal_position_bx(IDBX),
     legal_position_by(IDBY),
     point_in_board_position(BXBYXY)
      -> true
    ;
     true
    ).

point_in_tile(IDMXMY:-
    tile_x(IDTX),
    tile_y(IDTY),
    tile_size(IDSize),
    in_square(MXMYTXTYSize).

in_square(XYLeftTopSize:-
    in_interval(XLeftLeft+Size),
    in_interval(YTopTop+Size).

in_interval(VLowHigh:-
    V >= Low,
    V =< High.

point_in_board_position(BXBYXY:-
    game_tile_size(Size),
    board_position_top_left_coordinates(BXBYBCXBCY),
    in_square(XYBCXBCYSize).

board_position_top_left_coordinates(GridXGridYXY:-
    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(OldIDCtx% de-select OldID
    ;
    true
    ),
    asserta(is_selected(ID)),
    yield,
    draw_all_tile(IDCtx).


setup_hands([], []).
setup_hands([_+HandTiles|T], IDs:-
    setup_hand(HandTilesIDsIDTail),
    setup_hands(TIDTail).

setup_hand([], TailTail).
setup_hand([H-ID|T], [ID|OtherIDs], IDTail:-
    assert_data(HID),
    setup_hand(TOtherIDsIDTail).

hand_origin(1).

initial_hands_expanded(NumberOfPlayersExpandedHands:-
    initial_hands(NumberOfPlayersHands),
    expand_hands(HandsExpandedHands).

expand_hands([], []).
expand_hands([H|T], [EH|ET]) :-
    expand_hand(HEH),
    expand_hands(TET).

expand_hand(ID+BriefTilesID+ExpandedTiles:-
    game_tile_size(Size),
    expand_brief_tiles(BriefTilesIDSizeExpandedTiles).

expand_brief_tiles([], __, []).
expand_brief_tiles([H|T], HandIDSize, [EH|ET]) :-
    expand_brief_tile(HHandIDSizeEH),
    expand_brief_tiles(THandIDSizeET).

% [x, y,bx,by,size,colors,container]
expand_brief_tile(t(BoardXBoardYAbstractColorsTileID),
        HandID,
        Size,
        ts(XYBoardXBoardYSizeColors, container(HandID, hand))-TileID:-
    X is BoardX * Size,
    Y is BoardY * Size,
    abstract_colors(AbstractColorsColors).

abstract_colors([], []).
abstract_colors([AH|AT], [CH|CT]) :-
    abstract_color(AHCH),
    abstract_colors(ATCT).

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(Col1Player1Row1,[a,a,a,a], t01),
                            t(Col1Player1Row2,[b,a,a,a], t02),
                            t(Col1Player1Row3,[b,b,a,a], t03),
                            t(Col1Player1Row4,[b,a,b,a], t04),
                            t(Col2Player1Row1,[a,a,a,a], t05),
                            t(Col2Player1Row2,[b,a,a,a], t06),
                            t(Col2Player1Row3,[b,b,a,a], t07),
                            t(Col2Player1Row4,[b,a,b,a], t08)
                           ],
   Player2Tiles = [t(Col1Player2Row1,[b,b,b,b], t09),
                            t(Col1Player2Row2,[a,b,b,b], t10),
                            t(Col1Player2Row3,[a,a,b,b], t11),
                            t(Col1Player2Row4,[a,b,a,b], t12),
                            t(Col2Player2Row1,[b,b,b,b], t13),
                            t(Col2Player2Row2,[a,b,b,b], t14),
                            t(Col2Player2Row3,[a,a,b,b], t15),
                            t(Col2Player2Row4,[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(CtxTile:-
    tile_x(TileX),
    tile_y(TileY),
    tile_size(TileSize),
    Corners = [X > Y,X + Size > Y,X + Size > Y + SizeX > Y + Size],
    Center = (X + 0.5 * Size > Y + 0.5 * Size),
    tile_colors(TileColors),
    draw_triangles(CornersColorsCenterCtx),
    tile_bx(TileBX),
    tile_by(TileBY),
    tile_label(BXBYText),
    Ctx >> [
        save,
        fillStyle <:+ '#000',
        fillText(TextX+5, Y+10),
        restore
    ].


draw_triangles([P1P2|OtherCorners], [Color1|OtherColors], CenterCtx:-
   draw_triangle(P1P2Color1CenterCtx),
   draw_triangles1([P2|OtherCorners], OtherColorsP1CenterCtx).

draw_triangles1([P1], [Color], P2CenterCtx:-
   draw_triangle(P1P2ColorCenterCtx).
draw_triangles1([P1P2|OtherCorners], [Color1|OtherColors], FirstPCenterCtx:-
   draw_triangle(P1P2Color1CenterCtx),
   draw_triangles1([P2|OtherCorners], OtherColorsFirstPCenterCtx).

draw_triangle(P1x > P1yP2x > P2yColorCenterX > CenterYCtx:-
    Ctx >> [
        beginPath,
        moveTo(P1xP1y),
        lineTo(P2xP2y),
        lineTo(CenterXCenterY),
        closePath,

        save,
        fillStyle <:+ Color,
        fill,
        stroke,
        restore
    ].

draw_all_tiles(AllTilesCtxCWCH:-
    center_board,
    Ctx >> [
        fillStyle <:+ '#999',
        fillRect(0, 0, CWCH)
    ],
    draw_all_tiles1(AllTilesCtx).

draw_all_tiles1([], _).
draw_all_tiles1([H|T], Ctx:-
    draw_all_tile(HCtx),
    draw_all_tiles1(TCtx).

draw_all_tile(TileCtx:-
    (tile_in_inactive_hand(Tile) -> GlobalAlpha = 0.3; GlobalAlpha = 1),
    Ctx >> [
        save,
        globalAlpha <:+ GlobalAlpha
    ],
    draw_tile(CtxTile),
    Ctx >*> restore,
    (is_selected(Tile)
        -> draw_selected_tile_mark(TileCtx)
     ;
     true
    ),
    draw_replacements(TileCtx).

draw_replacements(TileCtx:-
    (game_replacements(Rs),
     member(TileRs)
       -> draw_replacement_tile_mark(TileCtx)
    ;
    true
    ).

center_board.

draw_selected_tile_mark(TileCtx:-
    tile_x(TileX),
    tile_y(TileY),
    tile_size(TileSize),

    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(GTColor),

    Ctx >> [
        save,

        lineWidth <:+ 3,
        strokeStyle <:+ Color,
        beginPath,
        moveTo(VerticalTopXVerticalTopY),
        lineTo(VerticalBottomXVerticalBottomY),
        closePath,
        stroke,

        beginPath,
        moveTo(HorizontalLeftXHorizontalLeftY),
        lineTo(HorizontalRightXHorizontalRightY),
        closePath,
        stroke,

        restore
    ].

draw_replacement_tile_mark(TileCtx:-
    tile_x(TileX),
    tile_y(TileY),
    tile_size(TileSize),

    MidX is X + (Size / 2),
    MidY is Y + (Size / 2),
    Adjust is Size / 4,

    game_turn(GT),
    highlight_color(GTColor),

    Ctx >> [
        save,
        lineWidth <:+ 3,
        strokeStyle <:+ Color,
        beginPath,
        arc(MidXMidYAdjust, 0, 2*pi),
        closePath,
        stroke,
        restore
    ].

container_id(container(ID_Type), ID).
container_type(container(_IDType), Type).

tile_label(BoardXBoardYText:-
    number_codes(BoardXBXCodes),
    number_codes(BoardYBYCodes),
    append_lists(["x", BXCodes, "y", BYCodes], TextCodes),
    atom_codes(TextTextCodes).

tile_in_inactive_hand(Tile:-
    tile_container(TileContainer),
    container_type(Container, hand),
    game_turn(TurnID),
    \+ container_id(ContainerTurnID).

tile_in_active_hand(Tile:-
    tile_container(TileContainer),
    container_type(Container, hand),
    game_turn(TurnID),
    container_id(ContainerTurnID).

highlight_color(1, '#CCFFCC').
highlight_color(2, '#CCCCFF').