Overblog
Editer la page Suivre ce blog Administration + Créer mon blog
/ / /

Code brut sans commentaire, l'article de démo est à venir !

CREATE TABLE cs_mouv (

    x number, 

    y number,

    x_dest number, 

    y_dest number,

    n_mouv number, 

    piece char(1),

    col char(1), 

    move_str varchar2(10),

    fic char(1) default 'N'

);

/

 

CREATE OR REPLACE VIEW pieces AS

SELECT x_dest x, y_dest y, max(piece) keep(dense_rank last order by n_mouv) piece

    , max(col) keep(dense_rank last order by n_mouv) col 

FROM (

    SELECT x_dest, y_dest, n_mouv

         , piece 

         , col

    FROM cs_mouv

    WHERE x_dest IS NOT NULL

    UNION ALL

    SELECT x, y, n_mouv

         , null 

         , null

    FROM cs_mouv

    )

GROUP BY x_dest, y_dest

/

CREATE OR REPLACE PACKAGE pkg_csboard

AS

    PROCEDURE init;

    PROCEDURE display(p_col IN CHAR DEFAULT 'B');

    PROCEDURE display_list;

    PROCEDURE csmove(p_move IN VARCHAR2);

    PROCEDURE cancel_move(p_cnt IN NUMBER);    

END pkg_csboard;

/

 

CREATE OR REPLACE PACKAGE BODY pkg_csboard

AS

    move_format EXCEPTION;

 

    PROCEDURE init

    IS    

    BEGIN

        DELETE FROM cs_mouv;

 

        INSERT INTO cs_mouv (x_dest, y_dest, n_mouv, piece, col, fic)

        SELECT mod(level-1,8)+1, case trunc((level - 1) / 8) when 0 then 2 else 7 end

            , -16 + level, 'P', case trunc((level - 1) / 8) when 0 then 'B' else 'N' end, 'Y'

        FROM dual 

        CONNECT BY level <= 16

        UNION ALL

        SELECT mod(level-1,2) * 7 + 1, trunc((level-1) / 2) * 7 + 1, -32 + level

            , 'T', CASE trunc((level-1) / 2) when 0 then 'B' else 'N' end, 'Y'

        FROM dual 

        CONNECT BY level <= 4

        UNION ALL

        SELECT 7 - mod(level-1,2) * 5, trunc((level-1) / 2) * 7 + 1, -28 + level

            , 'C', CASE trunc((level-1) / 2) when 0 then 'B' else 'N' end, 'Y'

        FROM dual 

        CONNECT BY level <= 4

        UNION ALL

        SELECT 6 - mod(level-1,2) * 3, trunc((level-1) / 2) * 7 + 1, -24 + level

            , 'F', CASE trunc((level-1) / 2) when 0 then 'B' else 'N' end, 'Y'

        FROM dual 

        CONNECT BY level <= 4

        UNION ALL

        SELECT 4, 1, -19, 'D', 'B', 'Y' FROM dual UNION ALL

        SELECT 5, 1, -18, 'R', 'B', 'Y' FROM dual UNION ALL

        SELECT 4, 8, -17, 'D', 'N', 'Y' FROM dual UNION ALL

        SELECT 5, 8, -16, 'R', 'N', 'Y' FROM dual;

 

        COMMIT;

 

        display;

 

    END init;

 

    PROCEDURE display(p_col CHAR default 'B')

    IS

    BEGIN              

        dbms_output.enable;

        FOR c IN (WITH cboard AS (    

                    SELECT mod(level-1, 8) + 1 x, trunc((level - 1) / 8) + 1 y 

                    FROM dual 

                    CONNECT BY level <= 64)

                , unord AS (

                    SELECT CASE p_col WHEN 'N' THEN c.y ELSE 9 - c.y END line_nr, to_char(c.y) || '|' || LISTAGG(COALESCE(p.piece || lower(p.col), '  ') || '|') WITHIN GROUP(ORDER BY c.x) disp_line 

                    FROM cboard c

                      LEFT OUTER JOIN pieces p ON c.x = p.x AND c.y = p.y       

                    GROUP BY c.y

                    UNION ALL

                    SELECT -0.5 + level, rpad('  ', 26, '_')

                    FROM DUAL

                    CONNECT BY level <= 9

                    UNION ALL

                    SELECT 9, '  ' || LISTAGG(' ' || chr(ASCII('a') + level - 1) || ' ') WITHIN GROUP (ORDER BY level)

                    FROM dual

                    CONNECT BY level <= 8

                    )

                SELECT disp_line

                FROM unord

                ORDER BY line_nr)

        LOOP

          dbms_output.put_line(c.disp_line);

        END LOOP;

        END display;

 

    PROCEDURE csmove(p_move IN VARCHAR2)

    IS

        input_x NUMBER;

        input_y NUMBER;

        input_x_dest NUMBER;

        input_y_dest NUMBER;

        x2 NUMBER;

        y2 NUMBER;

        x_dest2 NUMBER;

        y_dest2 NUMBER;        

        type_move NUMBER;

        turn CHAR(1);

 

        FUNCTION parse_move(p_move IN VARCHAR2, p_turn IN CHAR) RETURN NUMBER

        IS

            ret NUMBER; -- -1 erreur, 1 normal, 2 prise en passant, 3 promotion, 4 petit roque, 5 grand roque

        BEGIN

            IF REGEXP_LIKE(p_move, '([a-h][1-8]){2}(C|F|D|T)?') THEN

                input_x := ascii(substr(p_move, 1, 1)) - ascii('a') + 1;

                input_y := to_number(substr(p_move, 2, 1));

                input_x_dest := ascii(substr(p_move, 3, 1)) - ascii('a') + 1;

                input_y_dest := to_number(substr(p_move, 4, 1));

                ret := 1;

--                IF length(p_move) = 4 AND abs(input_x_dest - input_x) = 1 abs(input_y_dest - input_y) = 1 THEN

--                    

--                ELSIF  

--                    

--                END IF                

            ELSE 

                IF (p_move = 'oo') THEN

                    input_x := 5;

                    input_y := CASE p_turn WHEN 'B' THEN 1 ELSE 8 END;

                    input_x_dest := 7;

                    input_y_dest := input_y;

                    x2 := 8;

                    y2 := CASE p_turn WHEN 'B' THEN 1 ELSE 8 END;

                    x_dest2 := 6;

                    y_dest2 := input_y;                    

                    ret := 4;

                ELSE IF (p_move = 'ooo') THEN

                    input_x := 5;

                    input_y := CASE p_turn WHEN 'B' THEN 1 ELSE 8 END;

                    input_x_dest := 3;

                    input_y_dest := input_y;

                    x2 := 1;

                    y2 := CASE p_turn WHEN 'B' THEN 1 ELSE 8 END;

                    x_dest2 := 4;

                    y_dest2 := input_y;                    

                    ret := 5;

 

                    ELSE

                        ret := -1;

                    END IF;

                END IF;               

            END IF;    

 

            RETURN ret;

 

        END parse_move;         

 

        FUNCTION get_turn RETURN CHAR

        IS

            ret CHAR(1);

        BEGIN

 

            SELECT CASE COALESCE(max(col) keep(dense_rank last order by n_mouv), 'N') WHEN 'B' THEN 'N' ELSE 'B' END 

            INTO ret

            FROM cs_mouv

            WHERE fic = 'N';

 

            RETURN ret;

 

        END get_turn;

 

        PROCEDURE exec_move(p_move IN VARCHAR2, p_x IN NUMBER, p_y IN NUMBER, p_x_dest IN NUMBER, p_y_dest IN NUMBER, p_fic IN CHAR default 'N')

        IS

        BEGIN

            INSERT INTO cs_mouv(x, y, x_dest, y_dest, n_mouv, piece, col, move_str, fic)

            SELECT p_x, p_y, p_x_dest, p_y_dest

                , max((select max(n_mouv) + 1 from cs_mouv))

                , max(piece) keep(dense_rank last order by n_mouv)

                , max(col) keep(dense_rank last order by n_mouv)

                , p_move

                , p_fic

            FROM cs_mouv

            WHERE x_dest = p_x

              AND y_dest = p_y;            

        END exec_move;      

 

    BEGIN

        turn := get_turn;

 

        type_move := parse_move(p_move, turn);

        IF type_move < 0 THEN               

            RAISE move_format;

        ELSE

            exec_move(p_move, input_x, input_y, input_x_dest, input_y_dest);

            IF type_move IN (4, 5) THEN

                   exec_move(p_move, x2, y2, x_dest2, y_dest2, 'Y');     

            END IF;

        END IF;              

 

        COMMIT;

 

        display;

 

        dbms_output.put_line('OK !');

 

        EXCEPTION

            WHEN move_format THEN                

                dbms_output.put_line('Wrong move format');

                ROLLBACK;                

    END csmove;

 

    PROCEDURE display_list

    IS

    BEGIN

    FOR c IN (WITH cs_mouv_cont AS (

              SELECT x, y, x_dest, y_dest, piece, col

                , row_number() over(order by n_mouv) rk

                , move_str

              FROM cs_mouv

              WHERE fic = 'N')        

              SELECT lpad(round(a.rk / 2), 3) || '. ' || a.move_str || '    ' || b.move_str disp_line

              FROM cs_mouv_cont a

                LEFT OUTER JOIN cs_mouv_cont b ON b.rk = a.rk + 1

              WHERE mod(a.rk, 2) = 1        

              ORDER BY a.rk)

    LOOP

      dbms_output.put_line(c.disp_line);

    END LOOP;

 

    END display_list;

 

    PROCEDURE cancel_move(p_cnt IN NUMBER)

    IS

    BEGIN

        DELETE FROM cs_mouv

        WHERE n_mouv >= (SELECT min(n_mouv)

                         FROM (SELECT n_mouv, row_number() over(order by n_mouv desc) rk

                               FROM cs_mouv

                               WHERE fic = 'N')                        

                         WHERE rk <= p_cnt);

 

        COMMIT;

        display;

        dbms_output.put_line('Cancelled ' || to_char(p_cnt) || ' moves');

    END cancel_move;

 

 

END pkg_csboard;

/                    

 

show errors

/

Partager cette page
Repost0