-- title:  Diamond Mine
-- author: pixelbath
-- desc:   Unlike any match-3 game that ever existed! At least, I'm pretty sure...
-- script: lua

-- modes:
-- - diamond mine (ofc)
-- - poker?
-- - classic

local gems = {
    { spr=258 },
    { spr=260 },
    { spr=262 },
    { spr=264 },
    { spr=266 },
    { spr=268 },
    { spr=270 },
}

player = {
    x = 1, y = 1,
    cycle_t = 0, cycle_clr = 1, cycle_pal = { 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 13, 15, 14 },
    sel_x = 1, sel_y = 1, is_selected = false,
}

local board_w, board_h = 8, 8
local board = {}
local gem_sprites = {}
local board_x, board_y = 50, 4

function prt(text, x, y, color)
    print(text, x, y, color, true, 1, true)
end

function generate_gem(exclude_idx)
    -- exclude_idx = exclude_idx or 0
    local out_gem = math.random(1, #gems)
    if exclude_idx == out_gem then
        if out_gem + 1 > #gems then out_gem = 1 else outgem = out_gem + 1 end
    end
    return out_gem
end

function generate_gem_sprite(idx, xpos, ypos)
    return {
        spr = gems[idx].spr,
        x = xpos, y = ypos,
        dx = xpos, dy = ypos,
        t = 0,
    }
end

-- build the global board table from scratch
function generate_board(allow_matches)
    allow_matches = allow_matches or 1
    for y = 1, board_h do
        board[y], gem_sprites[y] = {}, {}
        for x = 1, board_w do
            local gem_idx = generate_gem()
            board[y][x] = gem_idx
            gem_sprites[y][x] = generate_gem_sprite(gem_idx, (x-1)*16, (y-1)*16)
        end
    end
end

function swap_gems(src_x, src_y, dest_x, dest_y)
    -- local xdiff, ydiff = math.abs(dest_x-src_x), math.abs(dest_y-src_y)
    -- if xdiff ~= 1 or ydiff ~= 1 then return end
    -- if xdiff == 1 and ydiff == 1 then return end

    local src_gem = board[src_y][src_x]
    local dest_gem = board[dest_y][dest_x]
    board[src_y][src_x] = dest_gem
    board[dest_y][dest_x] = src_gem

    -- set the new destination for swap
    if src_x ~= dest_x then
        gem_sprites[src_y][src_x].dx = (dest_x - 1) * 16
        gem_sprites[dest_y][dest_x].dx = (src_x - 1) * 16
    elseif src_y ~= dest_y then
        gem_sprites[src_y][src_x].dy = (dest_y - 1) * 16
        gem_sprites[dest_y][dest_x].dy = (src_y - 1) * 16
    end
end

-- return: table of x,y pair tables, or nil
function find_matches()
    local matches = {}

    -- brute force horizontal
    for y_test = 1, board_h do
        -- seed first gem
        local last_gem_x = board[y_test][1]
        local consecutive_x = 1
        for x_test = 2, board_w do
            local gem_idx = board[y_test][x_test]
            if last_gem_x == gem_idx then
                consecutive_x = consecutive_x + 1

                -- check once on the last column
                if x_test == board_w and consecutive_x >= 3 then
                    for i = x_test - consecutive_x + 1, x_test do
                        table.insert(matches, { i, y_test })
                    end
                end
            else
                if consecutive_x >= 3 then
                    for i = x_test - consecutive_x, x_test - 1 do
                        table.insert(matches, { i, y_test })
                    end
                end
                consecutive_x = 1
            end
            last_gem_x = gem_idx
        end
    end

    -- brute force vertical
    for x_test = 1, board_w do
        -- seed first gem
        local last_gem_y = board[1][x_test]
        local consecutive_y = 1
        for y_test = 2, board_h do
            local gem_idx = board[y_test][x_test]
            if last_gem_y == gem_idx then
                consecutive_y = consecutive_y + 1

                -- check once on the last row
                if y_test == board_h and consecutive_y >= 3 then
                    for i = y_test - consecutive_y + 1, y_test do
                        table.insert(matches, { x_test, i })
                    end
                end
            else
                if consecutive_y >= 3 then
                    for i = y_test - consecutive_y, y_test - 1 do
                        table.insert(matches, { x_test, i })
                    end
                end
                consecutive_y = 1
            end
            last_gem_y = gem_idx
        end
    end

    if #matches == 0 then
        return nil
    end
    
    return matches
end


function check_clear_matches()
    local matches = find_matches()
    if not matches then return end

    for i, gem in pairs(matches) do

    end
end

function board_draw()
    for y = 1, board_h do
        for x = 1, board_w do
            local sprite = gem_sprites[y][x]
            spr(sprite.spr, sprite.x + board_x, sprite.y + board_y, 0, 1, 0, 0, 2, 2)

            if math.abs(sprite.dx - sprite.x) < .01 then
                sprite.x = sprite.dx
            else
                sprite.x = sprite.x + (sprite.dx - sprite.x) / 2
            end
            if math.abs(sprite.dy - sprite.y) < .01 then
                sprite.y = sprite.dy
            else
                sprite.y = sprite.y + (sprite.dy - sprite.y) / 2
            end
        end
    end
end

function player_update()
    -- color cycle
    player.cycle_t = player.cycle_t + 1
    if player.cycle_t % 4 == 0 then player.cycle_clr = player.cycle_clr + 1 end
    if player.cycle_clr > #player.cycle_pal then player.cycle_clr = 1 end

    if btnp(0) then
        if player.y > 1 then
            player.y = player.y - 1
        end
    end
    if btnp(1) then
        if player.y < board_h then
            player.y = player.y + 1
        end
    end
    if btnp(2) then
        if player.x > 1 then
            player.x = player.x - 1
        end
    end
    if btnp(3) then
        if player.x < board_w then
            player.x = player.x + 1
        end
    end

    if btnp(4) then
        if not player.is_selected then
            player.is_selected = true
            player.sel_x = player.x
            player.sel_y = player.y
        else
            local x_mv = math.abs(player.x - player.sel_x) == 1
            local y_mv = math.abs(player.y - player.sel_y) == 1
            -- only move vertically and horizontally
            if (x_mv or y_mv) and not (x_mv and y_mv) then
                swap_gems(player.x, player.y, player.sel_x, player.sel_y)
            end
            player.is_selected = false
        end
    end
end

function player_draw()
    rectb((player.x-1)*16 + board_x, (player.y-1)*16 + board_y, 16, 16, player.cycle_pal[player.cycle_clr])
    if player.is_selected then
        rectb((player.sel_x-1)*16 + board_x, (player.sel_y-1)*16 + board_y, 16, 16, 12)
    end
end

function debug_match_draw()
    local matches = find_matches()
    if not matches then return end

    for i,_ in pairs(matches) do
        rectb((matches[i][1]-1)*16 + board_x, (matches[i][2]-1)*16 + board_y, 16, 16, 6)
        -- prt(matches[i][1] .. ', ' .. matches[i][2], 200, 7*i, 6)
    end
end

generate_board()

function TIC()
    player_update()

    cls()
    board_draw()
    debug_match_draw()
    player_draw()
end

-- <SPRITES>
-- 002:00000000000000ee0000e9ad000ebdbd00ebdbdb009dbccc08dbcccc0edccccc
-- 003:00000000e8000000dae80000bdae8000dcd9e800bdcd9800cbcbe980cccded80
-- 004:00000000000222220023cccc0334444401311121013111120131212201311212
-- 005:0000000022222000cccc32004444411021222120123221102322212032222120
-- 006:00000000000000010000001c000001cb00001cce0001cc3f001cc3ff01cc3fff
-- 007:0000000010000000f1000000ff100000f4f10000eeff1000f3eef100abbeee10
-- 008:0000000000000678000065670007567700766655076665550766555507775555
-- 009:00000000876000007556000077557000556787005557867055c67670ccc57670
-- 010:00000000000000010000011c00011e3c011e2244013224440133244401334444
-- 011:0000000010000000c1100000cc311000cc3331104cc33c1044c34410444c4410
-- 012:00000000000088880008a9ab0089a9bb08aaaabb008888990088889900088889
-- 013:0000000088880000b9fe8000bb9f9800ccb999809baaa80099a9980099888000
-- 014:0000000000000001000000010000001c000000c10000014300000c130000143f
-- 015:0000000000000000100000001000000031000000410000003410000034100000
-- 018:0edccccc08edcdcd008edcd90088ee9d00089ddd0000889b0000008800000000
-- 019:ccdb9c80cdcadb80dcdcd800abcdb800bddb8000cc8800008800000000000000
-- 020:0131212301311232013123220131322201221111002211110000000000000000
-- 021:2222212022222120222221202222222011111210111121000000000000000000
-- 022:01eeeffa001eeeab0001feeb00001ff2000001ff0000001f0000000100000000
-- 023:bbfbdc10bfbdc100fbdc1000bdd10000dd100000d10000001000000000000000
-- 024:076677770777666607776555007775550007565600007c660000077700000000
-- 025:7777887066667670555765705557c700657c700066c700007770000000000000
-- 026:0133444401343333014443330114443300011443000001130000000100000000
-- 027:4442441033323410333224103322e11033e11000311000001000000000000000
-- 028:000088890000888a000008890000088a0000008a000000980000000900000000
-- 029:9989000098880000a890000098800000a9000000a80000008000000000000000
-- 030:000041f300014f2e000412e20014fe2e004fffff01f18e8e0eeeeeee00000000
-- 031:f34100002f310000e29310002e231000ffff2e008e8e8fe0eeeeee1000000000
-- </SPRITES>

-- <PALETTE>
-- 000:1a1c2c5d275db13e55ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2612caace3ca1
-- </PALETTE>