#!/usr/bin/scriba

REM ****************************************************************************
REM
REM This is a port of my old ScriptBasic GTK demoprogram to the GTK-server.
REM
REM Originally published at july 20, 2002.
REM Rewritten at december 26, 2005 - PvE.
REM
REM Tested with Scriptbasic 2.0 and the GTK-server module 2.0.7 for Scriptbasic
REM
REM ****************************************************************************

IMPORT gtk.bas

GLOBAL CONST nl = "\n"
GLOBAL CONST FAKE = 12345
GLOBAL CONST EMPTY = 0
GLOBAL CONST WHITE = -1
GLOBAL CONST BLACK = 1
GLOBAL CONST GROUPIDSTART = 10
GLOBAL CONST CANVAS_WIDTH = 275
GLOBAL CONST CANVAS_HEIGHT = 246

REM ************************************************************** Main program

CALL Initialize_Global
CALL Create_Gopanel
CALL Draw_Board

REPEAT
        event = GUI("gtk_server_callback wait")
        IF event = newbutton THEN CALL New_Board
        IF event = "stone" THEN CALL Put_Stone
        IF event = buttoncapt THEN CALL Show_Prisoners
UNTIL event = quitbutton OR event = gopanel

GUI("gtk_exit 0")
END

REM ************************************************************** Concat arguments to GTK

FUNCTION GUI(g0, g1, g2, g3, g4, g5, g6, g7, g8, g9)

LOCAL result$

result$ = STR(g0) & " " & STR(g1) & " " & STR(g2) & " " & STR(g3) & " " & STR(g4) & " " & STR(g5) & " " & STR(g6) & " " & STR(g7) & " " & STR(g8) & " " & STR(g9)
GUI = GTK::gtk(result$)

END FUNCTION

REM ************************************************************** Initialize global parameters

SUB Initialize_Global
        GUI("gtk_init NULL NULL")
        REM This array keeps the current go-board, wipe Go playing board
        FOR j = 1 TO 9
        FOR i = 1 TO 9
                board[i,j] = EMPTY
        NEXT i
        NEXT j
        REM These keep the coordinates of the last move played
        lastmovex = 0
        lastmovey = 0
        REM These keep the total amount of captured stones for each color
        capturedbywhite = 0
        capturedbyblack = 0
END SUB

REM ************************************************************** Create Go panel

SUB Create_Gopanel
        gopanel = GUI("gtk_window_new 0")
        GUI("gtk_window_set_title", gopanel, "\"The Go panel Revived\"")
        GUI("gtk_widget_set_size_request", gopanel, 300, 350)
        gogrid = GUI("gtk_table_new", 55, 50, 1)
        GUI("gtk_container_add", gopanel, gogrid)
        frame = GUI("gtk_frame_new NULL")
        GUI("gtk_table_attach_defaults", gogrid, frame, 1, 49, 1, 43)
        GUI("gtk_frame_set_shadow_type", frame, 3)
        canvas = GUI("gtk_image_new")
        REM Create eventbox to catch mouseclick
        ebox = GUI("gtk_event_box_new")
        GUI("gtk_container_add", ebox, canvas)
        GUI("gtk_table_attach_defaults", gogrid, ebox, 2, 48, 2, 42)
        REM Connect mouse button signal to image
        GUI("gtk_server_connect", ebox, "button-press-event stone")
        radioblack = GUI("gtk_radio_button_new_with_label_from_widget NULL Black")
        GUI("gtk_table_attach_defaults", gogrid, radioblack, 20, 30, 44, 47)
        radiowhite = GUI("gtk_radio_button_new_with_label_from_widget", radioblack, "White")
        GUI("gtk_table_attach_defaults", gogrid, radiowhite, 20, 30, 48, 51)
        buttoncapt = GUI("gtk_button_new_with_label \"Show\nprison\"")
        GUI("gtk_table_attach_defaults", gogrid, buttoncapt, 10, 18, 44, 50)
        newbutton = GUI("gtk_button_new_with_label \"New\"")
        GUI("gtk_table_attach_defaults", gogrid, newbutton, 1, 9, 44, 50)
        quitbutton = GUI("gtk_button_new_with_label \"Quit\"")
        GUI("gtk_table_attach_defaults", gogrid, quitbutton, 41, 49, 44, 50)
        gostatus = GUI("gtk_statusbar_new")
        GUI("gtk_table_attach_defaults", gogrid, gostatus, 0, 50, 52, 55)
        cid = GUI("gtk_statusbar_get_context_id", gostatus, gopanel)
        GUI("gtk_statusbar_push", gostatus, cid, "\"New game started!\"")
        GUI("gtk_widget_show_all", gopanel)
        REM Create the pixmap
        gdkwin = GUI("gtk_widget_get_parent_window", canvas)
        pix = GUI("gdk_pixmap_new", gdkwin, CANVAS_WIDTH, CANVAS_HEIGHT, -1)
        gc = GUI("gdk_gc_new", pix)
        GUI("gtk_image_set_from_pixmap", canvas, pix, "NULL")
        REM Allocate memory for GdkColor with some random widget
        color = GUI("gtk_frame_new NULL")
        REM Now set foreground and backgroundcolors to WHITE
        GUI("gdk_color_parse #ffffff", color)
        GUI("gdk_gc_set_rgb_bg_color", gc, color)
        GUI("gdk_gc_set_rgb_fg_color", gc, color)
        REM Clear the complete pixmap with WHITE
        GUI("gdk_draw_rectangle", pix, gc, 1, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)
END SUB

REM ************************************************************ Draw the Go board

SUB Draw_Board
        LOCAL xfactor, yfactor
        REM Calculate square size
        xfactor = INT(CANVAS_WIDTH/9)
        yfactor = INT(CANVAS_HEIGHT/9)
        REM Draw vertical axes
        GUI("gdk_color_parse #000000", color)
        GUI("gdk_gc_set_rgb_fg_color", gc, color)
        FOR i = xfactor/2 TO CANVAS_WIDTH - xfactor/2 STEP xfactor
                GUI("gdk_draw_line", pix, gc, INT(i), INT(yfactor/2), INT(i), INT(yfactor/2)+yfactor*8)
        NEXT i
        REM Draw horizontal axes
        FOR i = yfactor/2 TO CANVAS_HEIGHT - yfactor/2 STEP yfactor
                GUI("gdk_draw_line", pix, gc, INT(xfactor/2), INT(i), INT(xfactor/2)+xfactor*8, INT(i))
        NEXT i
        REM Draw the positions of the stones
        FOR i = 1 TO 9
                FOR j = 1 TO 9
                        IF board[i,j] = BLACK THEN
                                GUI("gdk_color_parse #000000", color)
                                GUI("gdk_gc_set_rgb_fg_color", gc, color)
                                GUI("gdk_draw_arc", pix, gc, 1, (i-1)*xfactor, (j-1)*yfactor, xfactor-1, yfactor-1, 0, 360*64)
                        ELSE IF board[i,j] = WHITE THEN
                                GUI("gdk_color_parse #ffffff", color)
                                GUI("gdk_gc_set_rgb_fg_color", gc, color)
                                GUI("gdk_draw_arc", pix, gc, 1, (i-1)*xfactor, (j-1)*yfactor, xfactor-1, yfactor-1, 0, 360*64)
                                GUI("gdk_color_parse #000000", color)
                                GUI("gdk_gc_set_rgb_fg_color", gc, color)
                                GUI("gdk_draw_arc", pix, gc, 0, (i-1)*xfactor, (j-1)*yfactor, xfactor-1, yfactor-1, 0, 360*64)
                        END IF
                NEXT j
        NEXT i
        GUI("gtk_widget_queue_draw", canvas)
END SUB

REM ************************************************************ Reset the board & draw

SUB New_Board
        FOR j = 1 TO 9
                FOR i = 1 TO 9
                        board[j,i] = EMPTY
                NEXT i
        NEXT j
        GUI("gdk_color_parse #ffffff", color)
        GUI("gdk_gc_set_rgb_fg_color", gc, color)
        GUI("gdk_draw_rectangle", pix, gc, 1, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)
        CALL Draw_Board
        lastmovex = 0
        lastmovey = 0
        capturedbywhite = 0
        capturedbyblack = 0
        GUI("gtk_statusbar_pop", gostatus, cid)
        GUI("gtk_statusbar_push", gostatus, cid, "\"New game started!\"")
END SUB

REM ************************************************************ Show captured stones

SUB Show_Prisoners
        GUI("gtk_statusbar_pop", gostatus, cid)
        GUI("gtk_statusbar_push", gostatus, cid, "\"Captured by white: " & capturedbywhite & " - Captured by black: " & capturedbyblack & "\"")
END SUB

REM ************************************************************ Put a stone & draw

SUB Put_Stone

        LOCAL mousex, mousey, xfactor, yfactor

        mousex = VAL(GUI("gtk_server_mouse 0"))
        mousey = VAL(GUI("gtk_server_mouse 1"))
        xfactor = INT(CANVAS_WIDTH/9)
        yfactor = INT(CANVAS_HEIGHT/9)

        FOR j = 1 TO 9
                FOR i = 1 TO 9
                        IF (mousex>(j-1)*xfactor) AND (mousex<(j-1)*xfactor+xfactor) THEN
                                IF (mousey>(i-1)*yfactor) AND (mousey<((i-1)*yfactor+yfactor)) THEN
                                        IF (GUI("gtk_toggle_button_get_active", radioblack) = "1") THEN
                                                IF board[j,i] = EMPTY THEN
                                                        board[j,i] = BLACK
                                                        GUI("gtk_statusbar_pop", gostatus, cid)
                                                        GUI("gtk_statusbar_push", gostatus, cid, "\"Black played.\"")
                                                        lastmovex = j
                                                        lastmovey = i
                                                ELSE
                                                        GUI("gtk_statusbar_pop", gostatus, cid)
                                                        GUI("gtk_statusbar_push", gostatus, cid, "\"Cannot play here!\"")
                                                END IF
                                        ELSE
                                                IF board[j,i] = EMPTY THEN
                                                        board[j,i] = WHITE
                                                        GUI("gtk_statusbar_pop", gostatus, cid)
                                                        GUI("gtk_statusbar_push", gostatus, cid, "\"White played.\"")
                                                        lastmovex = j
                                                        lastmovey = i
                                                ELSE
                                                        GUI("gtk_statusbar_pop", gostatus, cid)
                                                        GUI("gtk_statusbar_push", gostatus, cid, "\"Cannot play here!\"")
                                                END IF
                                        END IF
                                END IF
                        END IF
                NEXT i
        NEXT j
        CALL Draw_Board
        CALL Captured_Stones
        CALL Determine_Suicide
END SUB

REM ************************************************************ Was last move suicide?

SUB Determine_Suicide
        LOCAL i, j, group, freedoms, counter, current
        REM Wipe groups board with fake value
        FOR j = 0 TO 10
                FOR i = 0 TO 10
                        groups[j,i] = FAKE
                NEXT i
        NEXT j
        REM Copy current playing board to groups board
        FOR j = 1 TO 9
                FOR i = 1 TO 9
                        groups[j,i] = board[j,i]
                NEXT i
        NEXT j
        REM Clear temp array's keeping stone positions
        FOR i = 1 to 81
                posx[i] = 0
                posy[i] = 0
        NEXT i
        REM Initialize local variables
        freedoms = 0
        counter = 1
        current = 1
        posx[current] = lastmovex
        posy[current] = lastmovey
        group = groups[lastmovex,lastmovey]
        groups[lastmovex,lastmovey] = -1*group
        DO
                IF groups[posx[current]-1,posy[current]] = EMPTY THEN
                        freedoms += 1
                ELSE IF groups[posx[current]-1,posy[current]] = group THEN
                        groups[posx[current]-1,posy[current]] = -1*group
                        counter += 1
                        posx[counter] = posx[current]-1
                        posy[counter] = posy[current]
                END IF
                IF groups[posx[current]+1,posy[current]] = EMPTY THEN
                        freedoms += 1
                ELSE IF groups[posx[current]+1,posy[current]] = group THEN
                        groups[posx[current]+1,posy[current]] = -1*group
                        counter += 1
                        posx[counter] = posx[current]+1
                        posy[counter] = posy[current]
                END IF
                IF groups[posx[current],posy[current]-1] = EMPTY THEN
                        freedoms += 1
                ELSE IF groups[posx[current],posy[current]-1] = group THEN
                        groups[posx[current],posy[current]-1] = -1*group
                        counter += 1
                        posx[counter] = posx[current]
                        posy[counter] = posy[current]-1
                END IF
                IF groups[posx[current],posy[current]+1] = EMPTY THEN
                        freedoms += 1
                ELSE IF groups[posx[current],posy[current]+1] = group THEN
                        groups[posx[current],posy[current]+1] = -1*group
                        counter += 1
                        posx[counter] = posx[current]
                        posy[counter] = posy[current]+1
                END IF
                current += 1
        LOOP UNTIL current > counter
        IF freedoms = 0 THEN
                board[lastmovex, lastmovey] = EMPTY
                GUI("gdk_color_parse #ffffff", color)
                GUI("gdk_gc_set_rgb_fg_color", gc, color)
                GUI("gdk_draw_rectangle", pix, gc, 1, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)
                CALL Draw_Board
                GUI("gtk_statusbar_pop", gostatus, cid)
                GUI("gtk_statusbar_push", gostatus, cid, "\"This is an illegal move! Play again...\"")
        END IF
END SUB

REM ************************************************************ Find captured stones

SUB Captured_Stones
        LOCAL i, j, group, freedoms, counter, current, total
        REM Wipe groups board
        FOR j = 0 TO 10
                FOR i = 0 TO 10
                        groups[j,i] = FAKE
                NEXT i
        NEXT j
        REM Copy current playing board to groups board
        FOR j = 1 TO 9
                FOR i = 1 TO 9
                        groups[j,i] = board[j,i]
                NEXT i
        NEXT j
        REM Clear temp array's keeping stone positions
        FOR i = 1 to 81
                posx[i] = 0
                posy[i] = 0
        NEXT i
        REM Initialize used variables
        total = 0
        FOR j = 1 TO 9
                FOR i = 1 TO 9
                        REM Check: place is empty and is not the last color played
                        IF (ABS(groups[j,i]) <> EMPTY) AND (groups[j,i]<>board[lastmovex,lastmovey]) THEN
                                freedoms = 0
                                counter = 1
                                current = 1
                                posx[current] = j
                                posy[current] = i
                                group = groups[j,i]
                                groups[j,i] = -5*group
                                DO
                                        IF groups[posx[current]-1,posy[current]] = EMPTY THEN
                                                freedoms += 1
                                        ELSE IF groups[posx[current]-1,posy[current]] = group THEN
                                                groups[posx[current]-1,posy[current]] = -5*group
                                                counter += 1
                                                posx[counter] = posx[current]-1
                                                posy[counter] = posy[current]
                                        END IF
                                        IF groups[posx[current]+1,posy[current]] = EMPTY THEN
                                                freedoms += 1
                                        ELSE IF groups[posx[current]+1,posy[current]] = group THEN
                                                groups[posx[current]+1,posy[current]] = -5*group
                                                counter += 1
                                                posx[counter] = posx[current]+1
                                                posy[counter] = posy[current]
                                        END IF
                                        IF groups[posx[current],posy[current]-1] = EMPTY THEN
                                                freedoms += 1
                                        ELSE IF groups[posx[current],posy[current]-1] = group THEN
                                                groups[posx[current],posy[current]-1] = -5*group
                                                counter += 1
                                                posx[counter] = posx[current]
                                                posy[counter] = posy[current]-1
                                        END IF
                                        IF groups[posx[current],posy[current]+1] = EMPTY THEN
                                                freedoms += 1
                                        ELSE IF groups[posx[current],posy[current]+1] = group THEN
                                                groups[posx[current],posy[current]+1] = -5*group
                                                counter += 1
                                                posx[counter] = posx[current]
                                                posy[counter] = posy[current]+1
                                        END IF
                                        current += 1
                                LOOP UNTIL current > counter

                                IF freedoms = 0 THEN
                                        counter = 1
                                        current = 1
                                        posx[current] = j
                                        posy[current] = i
                                        group = groups[j,i]
                                        groups[j,i] = EMPTY
                                        board[j,i] = EMPTY
                                        DO
                                                IF groups[posx[current]-1,posy[current]] = group THEN
                                                        groups[posx[current]-1,posy[current]] = EMPTY
                                                        board[posx[current]-1,posy[current]] = EMPTY
                                                        counter += 1
                                                        posx[counter] = posx[current]-1
                                                        posy[counter] = posy[current]
                                                END IF
                                                IF groups[posx[current]+1,posy[current]] = group THEN
                                                        groups[posx[current]+1,posy[current]] = EMPTY
                                                        board[posx[current]+1,posy[current]] = EMPTY
                                                        counter += 1
                                                        posx[counter] = posx[current]+1
                                                        posy[counter] = posy[current]
                                                END IF
                                                IF groups[posx[current],posy[current]-1] = group THEN
                                                        groups[posx[current],posy[current]-1] = EMPTY
                                                        board[posx[current],posy[current]-1] = EMPTY
                                                        counter += 1
                                                        posx[counter] = posx[current]
                                                        posy[counter] = posy[current]-1
                                                END IF
                                                IF groups[posx[current],posy[current]+1] = group THEN
                                                        groups[posx[current],posy[current]+1] = EMPTY
                                                        board[posx[current],posy[current]+1] = EMPTY
                                                        counter += 1
                                                        posx[counter] = posx[current]
                                                        posy[counter] = posy[current]+1
                                                END IF
                                                current += 1
                                        LOOP UNTIL current > counter
                                        GUI("gdk_color_parse #ffffff", color)
                                        GUI("gdk_gc_set_rgb_fg_color", gc, color)
                                        GUI("gdk_draw_rectangle", pix, gc, 1, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)
                                        CALL Draw_Board
                                        total += counter
                                END IF
                        END IF
                NEXT i
        NEXT j
        IF total > 0 THEN
                GUI("gtk_statusbar_pop", gostatus, cid)
                GUI("gtk_statusbar_push", gostatus, cid, "\"" & total & " stones captured!\"")
        END IF
        IF board[lastmovex, lastmovey] = WHITE THEN capturedbywhite += total
        IF board[lastmovex, lastmovey] = BLACK THEN capturedbyblack += total
END SUB