Dinfio Playground

Let's play with Dinfio!




Chess Game: Human vs AI

In this playground, we are going to build a human vs AI chess game.




What stuff we need?

For this chess game, we will need multiprocess module. Type the following command to install the module: $ dima install multiprocess

Here's the code:
' Chess in Dinfio. Human vs AI
 
import gui
import multiprocess
import fileio, string
import url, json
 
var box = array2d(8, 8)
 
var colour_box_light = [colour.hex("f7deb5"), colour.hex("f7deb5")]
var colour_box_dark = [colour.hex("b58b6a"), colour.hex("b58b6a")]
var colour_box_selected = [colour.hex("32df30"), colour.hex("32df30")]
var colour_box_valid = [colour.hex("9ddb88"), colour.white]
var colour_box_from = [colour.hex("92c4c3"), colour.hex("92c4c3")]
var colour_box_to = [colour.hex("3cb7a1"), colour.hex("3cb7a1")]
var colour_box_check = [colour.hex("ff8d21"), colour.hex("ff8d21")]
 
var checkmate = false
var is_promotion = false
var thinking = false
 
var depth_black = 12
var depth_white = 12
 
var box_from = ""
var box_to = ""
var last_from = ""
var last_to = ""
var last_from_piece = ""
var last_to_piece = ""
 
var last_mate = inf
var half_move = 0
var full_move = 1
 
var castling_k = true
var castling_q = true
var castling_K = true
var castling_Q = true
 
var en_passant = "-"
var current_fen = ""
 
var ai_assist_from = ""
var ai_assist_to = ""
var ai_assist_to_i = -1
var ai_assist_to_j = -1
 
start
    global window = gui_window("Chess in Dinfio")
 
    global label_title = gui_label("Chess in Dinfio\nHuman vs AI", window, 420, 20, 186, 100, align.centre)
    global label_winning_chance = gui_label("White's winning chance:\n50%", window, 420, 80, 186, 100, align.centre)
    global label_fen = gui_label("FEN", window, 20, 416, 622, 100)
 
    global button_ai_assistant = gui_button("AI Assistant", window, 420, 128, 186, 26)
    global button_reset = gui_button("Reset Board", window, 420, 158, 186, 26)
 
    global button_fen_copy = gui_button("Copy FEN", window, 420, 208, 186, 26)
    global button_fen_load = gui_button("Load FEN", window, 420, 238, 186, 26)
 
    global panel_promotion = gui_panel(window, 420, 208, 186, 200)
    global label_choose_promotion = gui_label("Choose a piece to promote:", panel_promotion, 0, 0, 186, 100, align.centre)
    global button_queen = gui_button("Queen", panel_promotion, 0, 24, 186, 26)
    global button_rook = gui_button("Rook", panel_promotion, 0, 54, 186, 26)
    global button_bishop = gui_button("Bishop", panel_promotion, 0, 84, 186, 26)
    global button_knight = gui_button("Knight", panel_promotion, 0, 114, 186, 26)
 
    global load_window, load_label, load_text, load_button_ok, load_button_cancel
    global load_window_shown = false
 
    label_title.setfontsize(16)
    label_title.setfontbold(true)
    label_winning_chance.setfontsize(12)
    label_winning_chance.setfontbold(true)
    label_choose_promotion.setfontsize(12)
    label_choose_promotion.setfontbold(true)
 
    button_reset.addevent(event.click, reset_board_click())
    button_ai_assistant.addevent(event.click, ai_assist())
    button_fen_copy.addevent(event.click, copy_fen())
    button_fen_load.addevent(event.click, load_fen())
 
    button_queen.addevent(event.click, promotion("Q"))
    button_rook.addevent(event.click, promotion("R"))
    button_bishop.addevent(event.click, promotion("B"))
    button_knight.addevent(event.click, promotion("N"))
 
    panel_promotion.setvisible(false)
 
    for i, 0, 7
        for j, 0, 7
            x = j * 48
            y = i * 48
 
            box[i][j] = gui_panel(window, x + 20, y + 20, 48, 48, true)
            box[i][j].piece = ""
            box[i][j].position = fromascii(97 + j) & (8 - i)
            box[i][j].flag = ""
            box[i][j].i = i
            box[i][j].j = j
 
            box[i][j].addevent(event.mouseleftdown, box_click(i, j))
        endfor
    endfor
 
    global button_black_turn = gui_button("Do Black Turn", window, 420, 286, 186, 26)
 
    button_black_turn.addevent(event.click, black_turn_click())
    button_black_turn.setvisible(false)
 
    load_assets()
    reset_board(true)
 
    window.setheight(448 + window.getheight() - window.getinnerheight())
    window.setwidth(622 + window.getwidth() - window.getinnerwidth())
 
    window.setbackgroundcolour(colour.white)
    window.show()
stop
 
function reset_board(render = false)
    checkmate = false
    is_promotion = false
    thinking = false
 
    depth_black = 12
    depth_white = 12
 
    box_from = ""
    box_to = ""
    last_from = ""
    last_to = ""
    last_from_piece = ""
    last_to_piece = ""
 
    last_mate = inf
    half_move = 0
    full_move = 1
 
    castling_k = true
    castling_q = true
    castling_K = true
    castling_Q = true
 
    en_passant = "-"
 
    ai_assist_from = ""
    ai_assist_to = ""
    ai_assist_to_i = -1
    ai_assist_to_j = -1
 
    for i, 0, 7
        for j, 0, 7
            box[i][j].piece = ""
            box[i][j].flag = ""
        endfor
    endfor
 
    box[0][0].piece = "r"; box[0][1].piece = "n"; box[0][2].piece = "b"; box[0][3].piece = "q"
    box[0][4].piece = "k"; box[0][5].piece = "b"; box[0][6].piece = "n"; box[0][7].piece = "r"
    box[1][0].piece = "p"; box[1][1].piece = "p"; box[1][2].piece = "p"; box[1][3].piece = "p"
    box[1][4].piece = "p"; box[1][5].piece = "p"; box[1][6].piece = "p"; box[1][7].piece = "p"
 
    box[7][0].piece = "R"; box[7][1].piece = "N"; box[7][2].piece = "B"; box[7][3].piece = "Q"
    box[7][4].piece = "K"; box[7][5].piece = "B"; box[7][6].piece = "N"; box[7][7].piece = "R"
    box[6][0].piece = "P"; box[6][1].piece = "P"; box[6][2].piece = "P"; box[6][3].piece = "P"
    box[6][4].piece = "P"; box[6][5].piece = "P"; box[6][6].piece = "P"; box[6][7].piece = "P"
 
    label_winning_chance.settext("White's winning chance:\n50%")
    button_black_turn.setvisible(false)
 
    if render; render(); endif
 
    current_fen = generate_fen("w")
    label_fen.settext("FEN: " & current_fen)
stop
 
function generate_fen(turn = "b")
    var result = ""
    var empty = 0
 
    for i, 0, 7
        empty = 0
 
        for j, 0, 7
            if box[i][j].piece == ""
                empty += 1
            else
                if empty > 0; result &= empty; endif
 
                result &= box[i][j].piece
                empty = 0
            endif
        endfor
 
        if empty > 0; result &= empty; endif
        result &= "/"
    endfor
 
    var castling = ""
 
    if castling_K; castling &= "K"; endif
    if castling_Q; castling &= "Q"; endif
    if castling_k; castling &= "k"; endif
    if castling_q; castling &= "q"; endif
 
    if castling == ""; castling = "-"; endif
 
    result = subleft(result, length(result) - 1) & " " & turn & " " & castling & " " & en_passant & " " & half_move & " " & full_move
    return result
stop
 
function set_fen(fen)
    process("includes/stockfish", [fen, 5], nothing, set_fen_callback())
    window.settitle("Chess in Dinfio - Validating FEN...")
stop
 
function set_fen_callback(data)
    thinking = false
    window.settitle("Chess in Dinfio")
 
    if attribute_exists(data, "error")
        messagebox("Invalid FEN.", "Chess in Dinfio")
        return
    endif
 
    reset_board()
 
    var parts = split(data.fen, " ")
 
    en_passant = parts[3]
    half_move = getnumber(parts[4])
    full_move = getnumber(parts[5])
 
    castling_K = find(parts[2], "K") != -1
    castling_Q = find(parts[2], "Q") != -1
    castling_k = find(parts[2], "k") != -1
    castling_q = find(parts[2], "q") != -1
 
    var positions = split(parts[0], "/")
    var p
 
    for i, 0, 7
        for j, 0, 7
            box[i][j].piece = ""
            box[i][j].flag = ""
        endfor
    endfor
 
    for i, 0, 7
        p = positions[i]
        j = 0
        k = 0
 
        while k < length(p) && j <= 7
            c = substring(p, k, 1)
 
            if getnumber(c) != 0
                j += getnumber(c) - 1
            else
                box[i][j].piece = c
            endif
 
            j += 1
            k += 1
        endwhile
    endfor
 
    render()
    current_fen = data.fen
 
    label_fen.settext("FEN: " & current_fen)
    label_winning_chance.settext("White's winning chance:\n-")
 
    if parts[1] == "b"
        button_black_turn.setvisible(true)
    endif
stop
 
function black_turn_click()
    black_turn()
    button_black_turn.setvisible(false)
stop
 
function black_turn()
    var fen = generate_fen()
    stockfish(fen)
stop
 
function stockfish(fen)
    thinking = true
    process("includes/stockfish", [fen, depth_black], nothing, stockfish_callback())
 
    window.settitle("Chess in Dinfio - Thinking...")
stop
 
function stockfish_callback(analysis)
    thinking = false
 
    ai_assist_from = ""
    ai_assist_to = ""
    ai_assist_to_i = -1
    ai_assist_to_j = -1
 
    window.settitle("Chess in Dinfio")
 
    if attribute_exists(analysis, "error")
        if analysis.error == "Invalid move."
            if last_mate == 1
                checkmate = true
                label_winning_chance.settext("Checkmate!\nWhite wins.")
 
                messagebox("Checkmate! White wins.", "Chess in Dinfio")
                return
            else
                messagebox("Invalid move.", "Chess in Dinfio", message.warning + message.ok)
                undo_last_move()
 
                return
            endif
        else
            messagebox(analysis.error, "Chess in Dinfio")
            undo_last_move()
 
            return
        endif
    endif
 
    last_mate = analysis.mate
    move(analysis.from, analysis.to)
 
    if analysis.promotion != ""
        var box_to = get_box(analysis.to)
        box_to.piece = analysis.promotion
 
        render_box(box_to.i, box_to.j)
    endif
 
    if is_check()
        label_winning_chance.settext("White's winning chance:\n" & round(analysis.win_chance * 100, 2) & "% - It's check!")
    else
        label_winning_chance.settext("White's winning chance:\n" & round(analysis.win_chance * 100, 2) & "%")
    endif
 
    if analysis.checkmate
        checkmate = true
        label_winning_chance.settext("Checkmate!\nBlack wins.")
 
        messagebox("Checkmate! Black wins.", "Chess in Dinfio")
    endif
stop
 
function ai_assist()
    if checkmate || is_promotion || thinking; return; endif
    var fen = generate_fen("w")
 
    process("includes/stockfish", [fen, depth_white], nothing, ai_assist_callback())
 
    thinking = true
    window.settitle("Chess in Dinfio - Thinking...")
stop
 
function ai_assist_callback(analysis)
    thinking = false
    depth_black = 10
 
    window.settitle("Chess in Dinfio")
 
    if attribute_exists(analysis, "error")
        messagebox("An error occurs. Please try again later.", "Chess in Dinfio")
        return
    endif
 
    if box_from != ""
        var current_from_box = get_box(box_from)
 
        ai_assist_from = ""
        ai_assist_to = ""
        ai_assist_to_i = -1
        ai_assist_to_j = -1
 
        box[current_from_box.i][current_from_box.j].flag = ""
 
        render_box(current_from_box.i, current_from_box.j)
        reset_valid_moves()
    endif
 
    var from = analysis.from
    var to = analysis.to
 
    var from_box = get_box(from)
    var to_box = get_box(to)
 
    ai_assist_from = from
    ai_assist_to = to
    ai_assist_to_i = to_box.i
    ai_assist_to_j = to_box.j
 
    box_from = from
    from_box.flag = "selected"
 
    render_box(from_box.i, from_box.j)
    get_valid_moves(from_box.i, from_box.j)
stop
 
function reset_board_click()
    i = messagebox("Are you sure you want to reset the board?", "Chess in Dinfio", message.warning + message.yesno)
 
    if i == message.yes
        reset_board(true)
    endif
stop
 
function copy_fen()
    clipboard.set(current_fen)
    messagebox("FEN is copied.", "Chess in Dinfio")
stop
 
function load_fen()
    if load_window_shown; return; endif
 
    load_window = gui_window("Load FEN", 100, 100, false, false)
    load_label = gui_label("FEN: ", load_window, 16, 10)
    load_text = gui_textbox("", load_window, 16, 32, 268, 24)
    load_button_ok = gui_button("Load", load_window, 16, 68, 100, 24)
    load_button_cancel = gui_button("Cancel", load_window, 124, 68, 100, 24)
 
    load_window.setheight(108 + load_window.getheight() - load_window.getinnerheight())
    load_window.setwidth(305 + load_window.getwidth() - load_window.getinnerwidth())
 
    load_button_ok.addevent(event.click, load_fen_click())
    load_button_cancel.addevent(event.click, close_load_window())
    load_window.addevent(event.close, load_window_closed())
 
    load_window.show(true)
    load_text.setfocus()
 
    load_window_shown = true
stop
 
function load_fen_click()
    var fen = trim(load_text.gettext())
    if fen == ""; return; endif
 
    set_fen(fen)
    load_window.close()
stop
 
function close_load_window()
    load_window.close()
stop
 
function load_window_closed()
    load_window_shown = false
    return true
stop
 
function box_click(i, j)
    if checkmate || is_promotion || thinking; return; endif
    position = box[i][j].position
 
    if box[i][j].piece != ""
        if position != box_from
            if box_from == ""
                if is_white_piece(i, j)
                    ' Select the box
 
                    box_from = position
                    box[i][j].flag = "selected"
 
                    get_valid_moves(i, j)
                endif
            else
                ' Move to valid position
 
                if box[i][j].flag == "valid"
                    box_to = box[i][j].position
                    move(box_from, box_to)
 
                    if !is_promotion; black_turn(); endif
                endif
            endif
        else
            box_from = ""
            box[i][j].flag = ""
 
            ai_assist_from = ""
            ai_assist_to = ""
            ai_assist_to_i = -1
            ai_assist_to_j = -1
 
            reset_valid_moves()
        endif
 
        render_box(i, j)
    else
        ' Move to valid position
 
        if box[i][j].flag == "valid"
            box_to = box[i][j].position
            move(box_from, box_to)
 
            if !is_promotion; black_turn(); endif
        endif
    endif
stop
 
function promotion(piece)
    var to_box = get_box(last_to)
 
    to_box.piece = piece
    is_promotion = false
 
    render_box(to_box.i, to_box.j)
    black_turn()
 
    panel_promotion.setvisible(false)
stop
 
function move(from, to)
    clear_last_move()
 
    var reset_half_move = false
    var from_box = get_box(from)
    var to_box = get_box(to)
 
    last_from = from
    last_to = to
    last_from_piece = from_box.piece
    last_to_piece = to_box.piece
 
    if is_opponent(from_box.piece, to_box.piece)
        half_move = 0
        reset_half_move = true
    endif
 
    if is_black_piece(from_box.i, from_box.j)
        full_move += 1
    endif
 
    if last_from_piece == "k" && from == "e8" && to == "g8"
        castling_k = false
        castling_q = false
 
        var castling_from_box = get_box("h8")
        var castling_to_box = get_box("f8")
 
        castling_from_box.piece = ""
        castling_to_box.piece = "r"
 
        render_box(castling_from_box.i, castling_from_box.j)
        render_box(castling_to_box.i, castling_to_box.j)
    endif
 
    if last_from_piece == "k" && from == "e8" && to == "c8"
        castling_k = false
        castling_q = false
 
        var castling_from_box = get_box("a8")
        var castling_to_box = get_box("d8")
 
        castling_from_box.piece = ""
        castling_to_box.piece = "r"
 
        render_box(castling_from_box.i, castling_from_box.j)
        render_box(castling_to_box.i, castling_to_box.j)
    endif
 
    if last_from_piece == "K" && from == "e1" && to == "g1"
        castling_K = false
        castling_Q = false
 
        var castling_from_box = get_box("h1")
        var castling_to_box = get_box("f1")
 
        castling_from_box.piece = ""
        castling_to_box.piece = "R"
 
        render_box(castling_from_box.i, castling_from_box.j)
        render_box(castling_to_box.i, castling_to_box.j)
    endif
 
    if last_from_piece == "K" && from == "e1" && to == "c1"
        castling_K = false
        castling_Q = false
 
        var castling_from_box = get_box("a1")
        var castling_to_box = get_box("d1")
 
        castling_from_box.piece = ""
        castling_to_box.piece = "R"
 
        render_box(castling_from_box.i, castling_from_box.j)
        render_box(castling_to_box.i, castling_to_box.j)
    endif
 
    if from_box.piece == "K"
        castling_K = false
        castling_Q = false
    endif
 
    if from_box.piece == "k"
        castling_k = false
        castling_q = false
    endif
 
    if from_box.piece == "R" && from_box.position == "a1"
        castling_Q = false
    endif
 
    if from_box.piece == "R" && from_box.position == "h1"
        castling_K = false
    endif
 
    if from_box.piece == "r" && from_box.position == "a8"
        castling_q = false
    endif
 
    if from_box.piece == "r" && from_box.position == "h8"
        castling_k = false
    endif
 
    to_box.piece = from_box.piece
    to_box.flag = "to"
 
    from_box.piece = ""
    from_box.flag = "from"
 
    box_from = ""
    box_to = ""
 
    if to_box.piece == "p" || to_box.piece == "P"
        half_move = 0
        reset_half_move = true
    endif
 
    if !reset_half_move
        half_move += 1
    endif
 
    if (last_from_piece == "P" || last_from_piece == "p") && en_passant != ""
        if to_box.i == 2 && en_passant == box[2][to_box.j].position
            box[3][to_box.j].piece = ""
            box[3][to_box.j].flag = ""
 
            render_box(3, to_box.j)
        elseif to_box.i == 5 && en_passant == box[5][to_box.j].position
            box[4][to_box.j].piece = ""
            box[4][to_box.j].flag = ""
 
            render_box(4, to_box.j)
        endif
    endif
 
    if (last_from_piece == "P" || last_from_piece == "p") && abs(to_box.i - from_box.i) == 2
        if to_box.i == 3
            en_passant = box[2][to_box.j].position
        else
            en_passant = box[5][to_box.j].position
        endif
    else
        en_passant = "-"
    endif
 
    reset_valid_moves()
 
    render_box(to_box.i, to_box.j)
    render_box(from_box.i, from_box.j)
 
    if to_box.i == 0 && to_box.piece == "P"
        is_promotion = true
        panel_promotion.setvisible(true)
    endif
 
    current_fen = generate_fen(iif(is_black_piece(to_box.i, to_box.j), "w", "b"))
    label_fen.settext("FEN: " & current_fen)
stop
 
function undo_last_move()
    var from_box = get_box(last_from)
    var to_box = get_box(last_to)
 
    from_box.piece = last_from_piece
    to_box.piece = last_to_piece
    from_box.flag = ""
    to_box.flag = ""
 
    half_move -= 1
    if half_move < 0; half_move = 0; endif
 
    render_box(to_box.i, to_box.j)
    render_box(from_box.i, from_box.j)
stop
 
function clear_last_move()
    var from_box = get_box(last_from)
    var to_box = get_box(last_to)
 
    if from_box == nothing; return; endif
 
    from_box.flag = ""
    to_box.flag = ""
 
    render_box(to_box.i, to_box.j)
    render_box(from_box.i, from_box.j)
stop
 
function get_valid_moves(i, j)
    var piece = box[i][j].piece
 
    valid_move_pawn(piece, i, j)
    valid_move_knight(piece, i, j)
    valid_move_rook(piece, i, j)
    valid_move_bishop(piece, i, j)
    valid_move_castling(piece, i, j)
stop
 
function valid_move_pawn(piece, i, j)
    if piece == "P"
        if i > 0
            if box[i - 1][j].piece == ""
                box[i - 1][j].flag = "valid"
                render_box(i - 1, j)
            endif
        endif
 
        if i == 6
            if box[i - 2][j].piece == "" && box[i - 1][j].piece == ""
                box[i - 2][j].flag = "valid"
                render_box(i - 2, j)
            endif
        endif
 
        if i > 0 && j > 0
            if box[i - 1][j - 1].piece != "" && !is_white_piece(i - 1, j - 1)
                box[i - 1][j - 1].flag = "valid"
                render_box(i - 1, j - 1)
            endif
 
            if box[i - 1][j - 1].position == en_passant
                box[i - 1][j - 1].flag = "valid"
                render_box(i - 1, j - 1)
            endif
        endif
 
        if i > 0 && j < 7
            if box[i - 1][j + 1].piece != "" && !is_white_piece(i - 1, j + 1)
                box[i - 1][j + 1].flag = "valid"
                render_box(i - 1, j + 1)
            endif
 
            if box[i - 1][j + 1].position == en_passant
                box[i - 1][j + 1].flag = "valid"
                render_box(i - 1, j + 1)
            endif
        endif
    endif
stop
 
function valid_move_knight(piece, i, j)
    if piece == "N"
        if i > 1 && j < 7
            if !is_white_piece(i - 2, j + 1)
                box[i - 2][j + 1].flag = "valid"
                render_box(i - 2, j + 1)
            endif
        endif
 
        if i > 1 && j > 0
            if !is_white_piece(i - 2, j - 1)
                box[i - 2][j - 1].flag = "valid"
                render_box(i - 2, j - 1)
            endif
        endif
 
        if i < 6 && j < 7
            if !is_white_piece(i + 2, j + 1)
                box[i + 2][j + 1].flag = "valid"
                render_box(i + 2, j + 1)
            endif
        endif
 
        if i < 6 && j > 0
            if !is_white_piece(i + 2, j - 1)
                box[i + 2][j - 1].flag = "valid"
                render_box(i + 2, j - 1)
            endif
        endif
 
        if i > 0 && j < 6
            if !is_white_piece(i - 1, j + 2)
                box[i - 1][j + 2].flag = "valid"
                render_box(i - 1, j + 2)
            endif
        endif
 
        if i > 0 && j > 1
            if !is_white_piece(i - 1, j - 2)
                box[i - 1][j - 2].flag = "valid"
                render_box(i - 1, j - 2)
            endif
        endif
 
        if i < 7 && j < 6
            if !is_white_piece(i + 1, j + 2)
                box[i + 1][j + 2].flag = "valid"
                render_box(i + 1, j + 2)
            endif
        endif
 
        if i < 7 && j > 1
            if !is_white_piece(i + 1, j - 2)
                box[i + 1][j - 2].flag = "valid"
                render_box(i + 1, j - 2)
            endif
        endif
    endif
stop
 
function valid_move_rook(piece, i, j)
    if piece == "R" || piece == "Q" || piece == "K"
        for x, j + 1, 7
            if is_white_piece(i, x); break; endif
 
            if box[i][x].piece == "" || is_black_piece(i, x)
                box[i][x].flag = "valid"
                render_box(i, x)
            endif
 
            if is_black_piece(i, x); break; endif
            if piece == "K"; break; endif
        endfor
 
        for x, j - 1, 0, -1
            if is_white_piece(i, x); break; endif
 
            if box[i][x].piece == "" || is_black_piece(i, x)
                box[i][x].flag = "valid"
                render_box(i, x)
            endif
 
            if is_black_piece(i, x); break; endif
            if piece == "K"; break; endif
        endfor
 
        for y, i + 1, 7
            if is_white_piece(y, j); break; endif
 
            if box[y][j].piece == "" || is_black_piece(y, j)
                box[y][j].flag = "valid"
                render_box(y, j)
            endif
 
            if is_black_piece(y, j); break; endif
            if piece == "K"; break; endif
        endfor
 
        for y, i - 1, 0, -1
            if is_white_piece(y, j); break; endif
 
            if box[y][j].piece == "" || is_black_piece(y, j)
                box[y][j].flag = "valid"
                render_box(y, j)
            endif
 
            if is_black_piece(y, j); break; endif
            if piece == "K"; break; endif
        endfor
    endif
stop
 
function valid_move_bishop(piece, i, j)
    if piece == "B" || piece == "Q" || piece == "K"
        var x = j + 1
        var y = i + 1
 
        while x <= 7 && y <= 7
            if is_white_piece(y, x); break; endif
 
            if box[y][x].piece == "" || is_black_piece(y, x)
                box[y][x].flag = "valid"
                render_box(y, x)
            endif
 
            if is_black_piece(y, x); break; endif
            if piece == "K"; break; endif
 
            x += 1
            y += 1
        endwhile
 
        x = j - 1
        y = i - 1
 
        while x >= 0 && y >= 0
            if is_white_piece(y, x); break; endif
 
            if box[y][x].piece == "" || is_black_piece(y, x)
                box[y][x].flag = "valid"
                render_box(y, x)
            endif
 
            if is_black_piece(y, x); break; endif
            if piece == "K"; break; endif
 
            x -= 1
            y -= 1
        endwhile
 
        x = j + 1
        y = i - 1
 
        while x <= 7 && y >= 0
            if is_white_piece(y, x); break; endif
 
            if box[y][x].piece == "" || is_black_piece(y, x)
                box[y][x].flag = "valid"
                render_box(y, x)
            endif
 
            if is_black_piece(y, x); break; endif
            if piece == "K"; break; endif
 
            x += 1
            y -= 1
        endwhile
 
        x = j - 1
        y = i + 1
 
        while x >= 0 && y <= 7
            if is_white_piece(y, x); break; endif
 
            if box[y][x].piece == "" || is_black_piece(y, x)
                box[y][x].flag = "valid"
                render_box(y, x)
            endif
 
            if is_black_piece(y, x); break; endif
            if piece == "K"; break; endif
 
            x -= 1
            y += 1
        endwhile
    endif
stop
 
function valid_move_castling(piece, i, j)
    if piece == "K"
        if i == 7 && j == 4
            if castling_K
                if box[7][5].piece == "" && box[7][6].piece == "" && is_position_safe(7, 4) && is_position_safe(7, 5) && is_position_safe(7, 6)
                    box[7][6].flag = "valid"
                    render_box(7, 6)
                endif
            endif
 
            if castling_Q
                if box[7][3].piece == "" && box[7][2].piece == "" && box[7][1].piece == "" && is_position_safe(7, 4) && is_position_safe(7, 3) && is_position_safe(7, 2)
                    box[7][2].flag = "valid"
                    render_box(7, 2)
                endif
            endif
        endif
    endif
stop
 
function is_position_safe(i, j)
    ' Pawn
 
    if i >= 1 && j >= 1; if box[i - 1][j - 1].piece == "p"; return false; endif; endif
    if i >= 1 && j <= 6; if box[i - 1][j + 1].piece == "p"; return false; endif; endif
 
 
    ' Knight
 
    if i >= 2 && j >= 1; if box[i - 2][j - 1].piece == "n"; return false; endif; endif
    if i >= 2 && j <= 6; if box[i - 2][j + 1].piece == "n"; return false; endif; endif
    if i >= 1 && j >= 2; if box[i - 1][j - 2].piece == "n"; return false; endif; endif
    if i >= 1 && j <= 5; if box[i - 1][j + 2].piece == "n"; return false; endif; endif
 
    if i <= 5 && j >= 1; if box[i + 2][j - 1].piece == "n"; return false; endif; endif
    if i <= 5 && j <= 6; if box[i + 2][j + 1].piece == "n"; return false; endif; endif
    if i <= 6 && j >= 2; if box[i + 1][j - 2].piece == "n"; return false; endif; endif
    if i <= 6 && j <= 5; if box[i + 1][j + 2].piece == "n"; return false; endif; endif
 
 
    ' Rook or Queen
 
    for x, i - 1, 0, -1
        if is_white_piece(x, j); break; endif
        if box[x][j].piece == "r" || box[x][j].piece == "q"; return false; endif
        if is_black_piece(x, j); break; endif
    endfor
 
    for x, i + 1, 7
        if is_white_piece(x, j); break; endif
        if box[x][j].piece == "r" || box[x][j].piece == "q"; return false; endif
        if is_black_piece(x, j); break; endif
    endfor
 
    for x, j - 1, 0, -1
        if is_white_piece(i, x); break; endif
        if box[i][x].piece == "r" || box[i][x].piece == "q"; return false; endif
        if is_black_piece(i, x); break; endif
    endfor
 
    for x, j + 1, 7
        if is_white_piece(i, x); break; endif
        if box[i][x].piece == "r" || box[i][x].piece == "q"; return false; endif
        if is_black_piece(i, x); break; endif
    endfor
 
 
    ' Bishop or Queen
 
    x = j + 1
    y = i - 1
 
    while x <= 7 && y >= 0
        if is_white_piece(y, x); break; endif
        if box[y][x].piece == "b" || box[y][x].piece == "q"; return false; endif
        if is_black_piece(y, x); break; endif
 
        x += 1
        y -= 1
    endwhile
 
    x = j - 1
    y = i - 1
 
    while x >= 0 && y >= 0
        if is_white_piece(y, x); break; endif
        if box[y][x].piece == "b" || box[y][x].piece == "q"; return false; endif
        if is_black_piece(y, x); break; endif
 
        x -= 1
        y -= 1
    endwhile
 
    x = j + 1
    y = i + 1
 
    while x <= 7 && y <= 7
        if is_white_piece(y, x); break; endif
        if box[y][x].piece == "b" || box[y][x].piece == "q"; return false; endif
        if is_black_piece(y, x); break; endif
 
        x += 1
        y += 1
    endwhile
 
    x = j - 1
    y = i + 1
 
    while x >= 0 && y <= 7
        if is_white_piece(y, x); break; endif
        if box[y][x].piece == "b" || box[y][x].piece == "q"; return false; endif
        if is_black_piece(y, x); break; endif
 
        x -= 1
        y += 1
    endwhile
 
    return true
stop
 
function is_check()
    var ii, jj
 
    for i, 0, 7
        for j, 0, 7
            if box[i][j].piece == "K"
                if !is_position_safe(i, j)
                    box[i][j].flag = "check"
                    render_box(i, j)
 
                    return true
                endif
 
                ii = i
                jj = j
            endif
        endfor
    endfor
 
    box[ii][jj].flag = ""
    render_box(ii, jj)
 
    return false
stop
 
function reset_valid_moves()
    for i, 0, 7
        for j, 0, 7
            if box[i][j].flag == "valid"
                box[i][j].flag = ""
                render_box(i, j)
            endif
        endfor
    endfor
stop
 
function is_white_piece(i, j)
    piece = box[i][j].piece
    return piece == "R" || piece == "N" || piece == "B" || piece == "Q" || piece == "K" || piece == "P"
stop
 
function is_black_piece(i, j)
    piece = box[i][j].piece
    return piece == "r" || piece == "n" || piece == "b" || piece == "q" || piece == "k" || piece == "p"
stop
 
function is_opponent(piece_1, piece_2)
    if piece_1 == "R" || piece_1 == "N" || piece_1 == "B" || piece_1 == "Q" || piece_1 == "K" || piece_1 == "P"
        if piece_2 == "r" || piece_2 == "n" || piece_2 == "b" || piece_2 == "q" || piece_2 == "k" || piece_2 == "p"
            return true
        endif
    endif
 
    if piece_1 == "r" || piece_1 == "n" || piece_1 == "b" || piece_1 == "q" || piece_1 == "k" || piece_1 == "p"
        if piece_2 == "R" || piece_2 == "N" || piece_2 == "B" || piece_2 == "Q" || piece_2 == "K" || piece_2 == "P"
            return true
        endif
    endif
 
    return false
stop
 
function render_box(i, j)
    box_colour = get_box_colour(i, j)
 
    box[i][j].draw_clear()
    box[i][j].draw_setbackgroundcolour(box_colour[0])
    box[i][j].draw_setpen(box_colour[1], 0)
    box[i][j].draw_rectangle(0, 0, 48, 48)
 
    if box[i][j].flag == "valid"
        if ai_assist_to == ""
            box[i][j].draw_setpen(colour_box_valid[0], 2)
 
            if !is_black_piece(i, j) && box[i][j].position != en_passant
                box[i][j].draw_circle(24, 24, 8)
            else
                box[i][j].draw_setpen(colour_box_valid[0], 3)
                box[i][j].draw_circle(24, 24, 18)
            endif
        else
            if ai_assist_to_i == i && ai_assist_to_j == j
                box[i][j].draw_setpen(colour_box_valid[0], 2)
                box[i][j].draw_setbrush(colour_box_valid[0])
 
                if !is_black_piece(i, j) && box[i][j].position != en_passant
                    box[i][j].draw_circle(24, 24, 8)
                else
                    box[i][j].draw_setpen(colour_box_valid[0], 3)
                    box[i][j].draw_circle(24, 24, 18)
                endif
            endif
        endif
    endif
 
    if box[i][j].piece != ""
        box[i][j].draw_image(attribute_get(piece_images, box[i][j].piece), 0, 0)
    endif
 
    box[i][j].refresh()
stop
 
function get_box(position)
    for i, 0, 7
        for j, 0, 7
            if position == box[i][j].position
                return box[i][j]
            endif
        endfor
    endfor
 
    return nothing
stop
 
function get_box_colour(i, j)
    if box[i][j].flag == "" || box[i][j].flag == "valid"
        if i % 2 == 0
            return iif(((i + 1) * (j + 1)) % 2 == 0, colour_box_dark, colour_box_light)
        else
            return iif(j % 2 == 0, colour_box_dark, colour_box_light)
        endif
    elseif box[i][j].flag == "selected"
        return colour_box_selected
    elseif box[i][j].flag == "from"
        return colour_box_from
    elseif box[i][j].flag == "to"
        return colour_box_to
    elseif box[i][j].flag == "check"
        return colour_box_check
    endif
stop
 
function load_assets()
    var path = getfoldername(getcurrentfile()) & "/includes/assets/"
 
    global piece_images = {
        p: image(path & "black-pawn.png"),
        n: image(path & "black-knight.png"),
        b: image(path & "black-bishop.png"),
        q: image(path & "black-queen.png"),
        k: image(path & "black-king.png"),
        r: image(path & "black-rook.png"),
 
        P: image(path & "white-pawn.png"),
        N: image(path & "white-knight.png"),
        B: image(path & "white-bishop.png"),
        Q: image(path & "white-queen.png"),
        K: image(path & "white-king.png"),
        R: image(path & "white-rook.png")
    }
stop
 
function render()
    for i, 0, 7
        for j, 0, 7
            render_box(i, j)
        endfor
    endfor
stop
 


Requirement: Dinfio 3.2.0 or later, and multiprocess module.

← Back to the Dinfio Playground / Download this programme