Files @ 67fca29a2e07
Branch filter:

Location: games/Awakening/london_checkers.lua

Silverwing
typo
checkers_game = room {
    var {
        board = {};
        selected = 0;
        select_lock = false;
    };
    nam = "checkers_game";
    nosave = true;
    noautosave = true;
    forcedsc = true;
    randomness = 15;
    depth = 6;
    cutoff_lo = -3;
    cutoff_hi = 3;
    draw_board = function(board)
        rval = {
            {0,0,0,0,0,0,0,0};
            {0,0,0,0,0,0,0,0};
            {0,0,0,0,0,0,0,0};
            {0,0,0,0,0,0,0,0};
            {0,0,0,0,0,0,0,0};
            {0,0,0,0,0,0,0,0};
            {0,0,0,0,0,0,0,0};
            {0,0,0,0,0,0,0,0};
        };
        
        for i = 1, #board do
            if board[i][3] then
                if board[i][4] then
                    rval[board[i][1]][board[i][2]] = 3;
                else
                    rval[board[i][1]][board[i][2]] = 1;
                end;
            else
                if board[i][4] then
                    rval[board[i][1]][board[i][2]] = 4;
                else
                    rval[board[i][1]][board[i][2]] = 2;
                end;
            end;
        end;
        
        return rval;
    end;
    calc_take = function(s, x, y, w, q, map)
        local rval = {};
        local r = nil;
        if w then
            -- белый рубит черного - рубит вверх
            if (map[x - 1][y - 1] == 2 or map[x - 1][y - 1] == 4)
                and map[x - 2][y - 2] == 0 and x - 2 > 0 and y - 2 > 0 then
                mcopy = deepcopy(map);
                r = s:calc_take(x - 2, y - 2, w, q or y == 2, mcopy);
                if #r == 0 then
                    rval[#rval + 1] = {1, {{x-1, y-1}}, q or y == 2, x-2, y-2};
                end;
                for i = 1, #r do
                    r[i][1] = r[i][1] + 1;
                    r[i][2][#r[i][2] + 1] = {x-1, y-1};
                    r[i][3] = r[i][3] or q or y == 2;
                    rval[#rval + 1] = r[i]
                end;
            end;
            if (map[x + 1][y - 1] == 2 or map[x + 1][y - 1] == 4)
                and map[x + 2][y - 2] == 0 and x + 2 < 9 and y - 2 > 0 then
                mcopy = deepcopy(map);
                r = s:calc_take(x + 2, y - 2, w, q or y == 2, mcopy);
                if #r == 0 then
                    rval[#rval + 1] = {1, {{x+1, y-1}}, q or y == 2, x+2, y-2};
                end;
                for i = 1, #r do
                    r[i][1] = r[i][1] + 1;
                    r[i][2][#r[i][2] + 1] = {x+1, y-1};
                    r[i][3] = r[i][3] or q or y == 2;
                    rval[#rval + 1] = r[i]
                end;
            end;
            --Дамка может рубить и вниз
            if q and (map[x - 1][y + 1] == 2 or map[x - 1][y + 1] == 4)
                and map[x - 2][y + 2] == 0 and x - 2 > 0 and y + 2 < 9 then
                mcopy = deepcopy(map);
                r = s:calc_take(x - 2, y + 2, w, q, mcopy);
                if #r == 0 then
                    rval[#rval + 1] = {1, {{x-1, y+1}}, q, x-2, y+2};
                end;
                for i = 1, #r do
                    r[i][1] = r[i][1] + 1;
                    r[i][2][#r[i][2] + 1] = {x-1, y+1};
                    r[i][3] = r[i][3] or q;
                    rval[#rval + 1] = r[i];
                end;
            end;
            if q and (map[x + 1][y + 1] == 2 or map[x + 1][y + 1] == 4)
                and map[x + 2][y + 2] == 0 and x + 2 < 9 and y + 2 < 9 then
                mcopy = deepcopy(map);
                r = s:calc_take(x + 2, y + 2, w, q, mcopy);
                if #r == 0 then
                    rval[#rval + 1] = {1, {{x+1, y+1}}, q, x+2, y+2};
                end;
                for i = 1, #r do
                    r[i][1] = r[i][1] + 1;
                    r[i][2][#r[i][2] + 1] = {x+1, y+1};
                    r[i][3] = r[i][3] or q;
                    rval[#rval + 1] = r[i];
                end;
            end;
        else
            --черный рубит белого - рубит вниз
            if (map[x - 1][y + 1] == 1 or map[x - 1][y + 1] == 3)
                and map[x - 2][y + 2] == 0 and x - 2 > 0 and y + 2 < 9 then
                mcopy = deepcopy(map);
                r = s:calc_take(x - 2, y + 2, w, q or y == 6, mcopy);
                if #r == 0 then
                    rval[#rval + 1] = {1, {{x-1, y+1}}, q or y == 6, x-2, y+2};
                end;
                for i = 1, #r do
                    r[i][1] = r[i][1] + 1;
                    r[i][2][#r[i][2] + 1] = {x-1, y+1};
                    r[i][3] = r[i][3] or q or y == 6;
                    rval[#rval + 1] = r[i]
                end;
            end;
            if (map[x + 1][y + 1] == 1 or map[x + 1][y + 1] == 3)
                and map[x + 2][y + 2] == 0 and x + 2 < 9 and y + 2 < 9 then
                mcopy = deepcopy(map);
                r = s:calc_take(x + 2, y + 2, w, q or y == 6, mcopy);
                if #r == 0 then
                    rval[#rval + 1] = {1, {{x+1, y+1}}, q or y == 6, x+2, y+2};
                end;
                for i = 1, #r do
                    r[i][1] = r[i][1] + 1;
                    r[i][2][#r[i][2] + 1] = {x+1, y+1};
                    r[i][3] = r[i][3] or q or y == 2;
                    rval[#rval + 1] = r[i]
                end;
            end;
            --Дамка может рубить и вниз
            if q and (map[x - 1][y - 1] == 1 or map[x - 1][y - 1] == 3)
                and map[x - 2][y - 2] == 0 and x - 2 > 0 and y - 2 > 0 then
                mcopy = deepcopy(map);
                r = s:calc_take(x - 2, y - 2, w, q, mcopy);
                if #r == 0 then
                    rval[#rval + 1] = {1, {{x-1, y-1}}, q or y == 6, x-2, y-2};
                end;
                for i = 1, #r do
                    r[i][1] = r[i][1] + 1;
                    r[i][2][#r[i][2] + 1] = {x-1, y-1};
                    r[i][3] = r[i][3] or q;
                    rval[#rval + 1] = r[i];
                end;
            end;
            if q and (map[x + 1][y - 1] == 1 or map[x + 1][y - 1] == 3)
                and map[x + 2][y - 2] == 0 and x + 2 < 9 and y - 2 > 0 then
                mcopy = deepcopy(map);
                r = s:calc_take(x + 2, y - 2, w, q, mcopy);
                if #r == 0 then
                    rval[#rval + 1] = {1, {{x+1, y-1}}, q or y == 6, x+2, y-2};
                end;
                for i = 1, #r do
                    r[i][1] = r[i][1] + 1;
                    r[i][2][#r[i][2] + 1] = {x+1, y-1};
                    r[i][3] = r[i][3] or q;
                    rval[#rval + 1] = r[i];
                end;
            end;
        end;
        return rval;
    end;
    calc_turn = function(s, d, w, board)
        if d > s.depth then
            return nil, 0;
        end;
        local cost = 0;
        local turns = {};
        local bmap = s.draw_board(board);
        local takes = false;
        for i = 1, #board do
            --Рубка обязательна, поэтому сперва проверяем рубки
            if board[i][3] == w then
                -- своя фигура. Проверяем рубки
                local r = s:calc_take(board[i][1], board[i][2], w, board[i][4], bmap);
                if #r > 0 then
                    takes = true;
                    for j = 1, #r do
                        --Восстанавливаем состояние поля после рубки и уходим глубже
                        local bcopy = deepcopy(board);
                        for k = #bcopy, 1, -1 do
                            for l = 1, #r[j][2] do
                                if r[j][2][1] == bcopy[k][2] and r[j][2][1] == bcopy[k][2] then
                                    table.remove(bcopy, k);
                                    break;
                                end;
                            end;
                        end;
                        local rr, pts = s:calc_turn(d + 1, not w, bcopy);
                        turns[#turns + 1] = {board[i][1], board[i][2], r[j][4], r[j][5], r[j][2], r[j][1] - pts};
                    end;
                end;
            end;
        end;
        -- Если была рубка, не обрабатываем дальше
        if takes then
            table.sort(turns, function(a,b) 
                return a[6] > b[6];
            end);
            return turns[0], turns[0][6];
        end;
        for i = 1, #board do
            if board[i][3] == w then
                --Проверяем ходы
                if q or w then
                    --белая или дамка - ходит вверх
                    if bmap[board[i][1] - 1][board[i][2] - 1] == 0 then
                        local bcopy = deepcopy(board);
                        bcopy[i][1] = bcopy[i][1] - 1;
                        bcopy[i][2] = bcopy[i][2] - 1;
                        local rr, pts = s:calc_turn(d + 1, not w, bcopy);
                        turns[#turns + 1] = {board[i][1], board[i][2], bcopy[i][1], bcopy[i][2], nil, - pts};
                    end;
                    if bmap[board[i][1] - 1][board[i][2] + 1] == 0 then
                        local bcopy = deepcopy(board);
                        bcopy[i][1] = bcopy[i][1] - 1;
                        bcopy[i][2] = bcopy[i][2] + 1;
                        local rr, pts = s:calc_turn(d + 1, not w, bcopy);
                        turns[#turns + 1] = {board[i][1], board[i][2], bcopy[i][1], bcopy[i][2], nil, - pts};
                    end;
                end;
                if q or not w then
                    --черная или дамка - ходит вниз
                    if bmap[board[i][1] + 1][board[i][2] - 1] == 0 then
                        local bcopy = deepcopy(board);
                        bcopy[i][1] = bcopy[i][1] + 1;
                        bcopy[i][2] = bcopy[i][2] - 1;
                        local rr, pts = s:calc_turn(d + 1, not w, bcopy);
                        turns[#turns + 1] = {board[i][1], board[i][2], bcopy[i][1], bcopy[i][2], nil, - pts};
                    end;
                    if bmap[board[i][1] + 1][board[i][2] + 1] == 0 then
                        local bcopy = deepcopy(board);
                        bcopy[i][1] = bcopy[i][1] + 1;
                        bcopy[i][2] = bcopy[i][2] + 1;
                        local rr, pts = s:calc_turn(d + 1, not w, bcopy);
                        turns[#turns + 1] = {board[i][1], board[i][2], bcopy[i][1], bcopy[i][2], nil, - pts};
                    end;
                end;
            end;
        end;

        table.sort(turns, function(a,b) 
            return a[6] > b[6];
        end);
        return turns[0], turns[0][6];
    end;
    enemy_turn = function(s)
    end;
    click = function(s, x, y)
        x = math.floor((x - 4) / 24) + 1;
        y = math.floor((y - 4) / 24) + 1;
        if x > 0 and x < 9 and y > 0 and y < 9 then
            for i = 1,#s.board do
                if s.board[i][1] == x and s.board[i][2] == y then
                    if s.board[i][3] then
                        s.selected = i;
                        walkin(here());
                        return;
                    else
                        --Может рубим?
                        if s.selected > 0 then
                            print("q");
                            local dx = x - s.board[s.selected][1];
                            local dy = y - s.board[s.selected][2];
                            if s.board[s.selected][4] then
                                if math.abs(dx) == 1 and math.abs(dy) == 1 then
                                    s.board[s.selected][1] = s.board[s.selected][1] + dx * 2;
                                    s.board[s.selected][2] = s.board[s.selected][2] + dy * 2;
                                    s.selected = 0;
                                    walkin(here());
                                    return;
                                end;
                            else
                                if math.abs(dx) == 1 and dy == -1 then
                                    s.board[s.selected][1] = s.board[s.selected][1] + dx * 2;
                                    s.board[s.selected][2] = s.board[s.selected][2] + dy * 2;
                                    s.selected = 0;
                                    walkin(here());
                                    return;
                                end;
                            end;
                    end;
                        return;
                    end;
                end;
            end;
            
            if s.selected > 0 then
                local dx = x - s.board[s.selected][1];
                local dy = y - s.board[s.selected][2];
                print(dx, dy);
                if s.board[s.selected][4] then
                    if math.abs(dx) == 1 and math.abs(dy) == 1 then
                        s.board[s.selected][1] = x;
                        s.board[s.selected][2] = y;
                        s.selected = 0;
                        walkin(here());
                        return;
                    end;
                else
                    if math.abs(dx) == 1 and dy == -1 then
                        s.board[s.selected][1] = x;
                        s.board[s.selected][2] = y;
                        print(s.board[s.selected][1], s.board[s.selected][2])
                        s.selected = 0;
                        walkin(here());
                        return;
                    end;
                end;
            end;
            s.selected = 0;
        
            
        end;
        walkin(here());
    end;
    disp = "Шашки";
    reset = function(s)
        s.board = {
            {2, 3, false, false};
            {4, 3, false, false};
            {6, 3, false, false};
            {8, 3, false, false};
            
            --{1, 2, false, false};
            --{3, 2, false, false};
            --{5, 2, false, false};
            --{7, 2, false, false};
            
            {2, 5, false, false};
            {4, 5, false, false};
            {6, 5, false, false};
            {8, 5, false, false};
            
            {1, 6, true, false};
            {3, 6, true, false};
            {5, 6, true, false};
            {7, 6, true, false};
            
            {2, 7, true, false};
            {4, 7, true, false};
            {6, 7, true, false};
            {8, 7, true, false};
            
            {1, 8, true, false};
            {3, 8, true, false};
            {5, 8, true, false};
            {7, 8, true, false};
        };
    end;
    pic = function(s)
        local rval = "images/checkerboard.png";
        if s.selected > 0 then
            rval = rval .. [[;box:24x24,red,32@]] .. tostring(s.board[s.selected][1] * 24 - 20) .. "," .. tostring(s.board[s.selected][2] * 24 - 20);
        end;
        for i = 1, #s.board do
            if s.board[i][3] and s.board[i][4] then
                rval = rval .. [[;images/checkerwhiteq.png@]] .. tostring(s.board[i][1] * 24 - 20) .. "," .. tostring(s.board[i][2] * 24 - 20);
            elseif not s.board[i][3] and s.board[i][4] then
                rval = rval .. [[;images/checkerblackq.png@]] .. tostring(s.board[i][1] * 24 - 20) .. "," .. tostring(s.board[i][2] * 24 - 20);
            elseif s.board[i][3] and not s.board[i][4] then
                rval = rval .. [[;images/checkerwhite.png@]] .. tostring(s.board[i][1] * 24 - 20) .. "," .. tostring(s.board[i][2] * 24 - 20);
            elseif not s.board[i][3] and not s.board[i][4] then
                rval = rval .. [[;images/checkerblack.png@]] .. tostring(s.board[i][1] * 24 - 20) .. "," .. tostring(s.board[i][2] * 24 - 20);
            end;
        end;
        return rval;
    end;
};