------------------------------------------------------------------------------
-- This is a script file for U61 by U-Foot (www.ufoot.org ufoot@ufoot.org)  --
-- It is free software, protected by the GPL (www.fsf.org)                  --
--                                                                          --
-- Do not hesitate to modify this file to change the behavior of U61,       --
-- that's exactly what it's done for!                                       --
------------------------------------------------------------------------------


------------------------------------------------------------------------------
--                                                                          --
-- U U    6   1            U U   FFF  O   O  TTT                            --
-- U U   6   11   b        U U   F   O O O O  T                             --
-- U U - 66   1   bb  y y  U U - FF  O O O O  T                             --
-- U U   6 6  1   b b  y   U U   F   O O O O  T                             --
--  U     6   1   bb   y    U    F    O   O   T                             --
--                                                                          --
-- U61 is another block based game                                          --
-- Copyright (C) 2000 Christian Mauduit (ufoot@ufoot.org / www.ufoot.org)   --
--                                                                          --
-- This program is free software; you can redistribute it and/or            --
-- modify it under the terms of the GNU General Public License              --
-- as published by the Free Software Foundation; either version 2           --
-- of the License, or (at your option) any later version.                   --
--                                                                          --
-- This program is distributed in the hope that it will be useful,          --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of           --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            --
-- GNU General Public License for more details.                             --
--                                                                          --
-- You should have received a copy of the GNU General Public License        --
-- along with this program; if not, write to the Free Software              --
-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA--
--                                                                          --
-- This project is also available on SourceForge  (http://sourceforge.net)  --
------------------------------------------------------------------------------

-- vertical blocks with 3 squares fall. one can translate them and change
-- the colors, but not rotate them. the goal is to have lines or diags
-- of 3 squares of the same color


-- shape definition ----------------------------------------------------------

function user_new_shape(num)
    return num
end 

function user_do_shape(num)
    local nb_colors

    nb_colors=morecolors_get_nb()

    colored_vertical_bar(3,nb_colors,num)
end


-- actions -------------------------------------------------------------------

function user_rotate_left()
    cycle_forward()    
end

function user_rotate_right()
    cycle_backward()    
end

function user_move_left()
    goofy_left()
end

function user_move_right()
    goofy_right()
end

function user_move_down()
    translation_y(1)
end

function user_use_antidote()
    u61_cancel_curse(u61_get_oldest_curse())
end

-- pattern match -------------------------------------------------------------

function user_match_pattern(match_count)
    return color_match_pattern(match_count,3)
end

function user_land()

end

function user_square_blown_up(x,y)
    utils_shift_column_down(x,y)
end

-- curse functions  ----------------------------------------------------------

function user_new_curse(num)
    num=mod(num,100)

    if num<10 then
        num=ID_CURSE_ANTIDOTE
    elseif num<50 then
        num=ID_CURSE_MIXEDLINE
    elseif num<60 then
        num=ID_CURSE_GOOFY
    elseif num<80 then
        num=ID_CURSE_CLEAR
    elseif num<90 then
        num=ID_CURSE_WIND
    elseif num<100 then
        num=ID_CURSE_MORECOLORS
    end

    return num
end

function user_do_curse(num,sent)
    if (num==ID_CURSE_ANTIDOTE) then
        antidote_do_curse()
    elseif (num==ID_CURSE_MIXEDLINE) then
        mixedline_do_curse(sent)
    elseif (num==ID_CURSE_GOOFY) then
        goofy_do_curse(sent)
    elseif (num==ID_CURSE_CLEAR) then
        clear_do_curse()
    elseif (num==ID_CURSE_WIND) then
        wind_do_curse(sent)
    elseif (num==ID_CURSE_MORECOLORS) then
        morecolors_do_curse(sent)
    end    
end

function user_get_curse_name(num)
    name="surprise"

    if (num==ID_CURSE_ANTIDOTE) then
        name="antidote"
    elseif (num==ID_CURSE_MIXEDLINE) then
        name="line"
    elseif (num==ID_CURSE_GOOFY) then
        name="goofy"
    elseif (num==ID_CURSE_CLEAR) then
        name="clear"
    elseif (num==ID_CURSE_WIND) then
        name="wind"
    elseif (num==ID_CURSE_MORECOLORS) then
        name="7colors"
    end

    return name
end

-- other functions -----------------------------------------------------------

function user_time_callback()
    u61_add_score(10)
    wind_time_callback()
end


-- various functions used for pattern matching -------------------------------

function utils_shift_column_down(x_col,y_bottom)
    local y
    local color

    y=y_bottom
    while y>=1 do
        color=u61_get_square_color(x_col,y-1)
        u61_set_square_color(x_col,y,color)
        y=y-1
    end
    u61_set_square_color(x_col,0,-1)

    if u61_get_curse_x()==x_col and u61_get_curse_y()<y_bottom then
        u61_set_curse_y(u61_get_curse_y()+1)
    end
end


-- Functions used in many curse scripts --------------------------------------

function utils_shift_map_up()
    local x
    local y
    local width
    local height
    local color

    width=u61_get_width()
    height=u61_get_height() 
    y=0
    while y<height-1 do
        x=0
        while x<width do
            color=u61_get_square_color(x,y+1)
            u61_set_square_color(x,y,color)
            x=x+1
        end
        y=y+1
    end

    u61_set_curse_y(u61_get_curse_y()-1)
end

function utils_clear_map()
    local x
    local y
    local width
    local height

    width=u61_get_width()
    height=u61_get_height() 
    y=0
    while y<height do
        x=0
        while x<width do
            u61_set_square_color(x,y,-1)
            x=x+1
        end
        y=y+1
    end
end

function utils_switch_lines(y1,y2)
    local x
    local color

    x=u61_get_width()-1
    while x>=0 do
        color=u61_get_square_color(x,y1)
        u61_set_square_color(x,y1,u61_get_square_color(x,y2))
        u61_set_square_color(x,y2,color)
        x=x-1
    end
end

function utils_get_highest_square_y()
    local x
    local y
    local width
    local height
    local min_y	

    width=u61_get_width()
    height=u61_get_height()
    min_y=height 
    y=0
    while y<height do
        x=0
        while x<width do
            if u61_get_square_color(x,y)>=0 then
                min_y=y
                x=width
                y=height
            end
            x=x+1
        end
        y=y+1
    end 

    return min_y   
end
-- vertical colored bar of any size ------------------------------------------

function colored_vertical_bar(y_size,nb_colors,num)
    local y

    y=0
    while y<y_size do
        u61_add_item(0,y,mod(num,nb_colors))
        num=floor(num/7)
        y=y+1
    end
end



-- defines translations ------------------------------------------------------

function translation_x(x)
    u61_set_block_x(u61_get_block_x()+x)
end

function translation_y(y)
    u61_set_block_y(u61_get_block_y()+y)
end

function translation_x_check(x)
    local i
    local dx
	
    if x>0 then
        dx=1
    else
        x=-x
        dx=-1
    end

    i=x
    while i>0 do
        translation_x(dx)
        if u61_is_block_ok()==0 then
            translation_x(-dx)
            i=0
        end
        i=i-1	          
    end
end

function translation_y_check(y)
    local i
    local dy
	
    if y>0 then
        dy=1
    else
        y=-y
        dy=-1
    end

    i=y
    while i>0 do
        translation_y(dy)
        if u61_is_block_ok()==0 then
            translation_y(-dy)
            i=0
        end
        i=i-1		          
    end
end


-- defines color cycling -----------------------------------------------------

function cycle_forward()
    local size
    local i
    local temp_color
 
    size=u61_get_nb_items()

    temp_color=u61_get_item_color(size-1)

    i=size-1
    while i>0 do
        u61_set_item_color(i,u61_get_item_color(i-1))
        i=i-1
    end
        
    u61_set_item_color(0,temp_color)
end

function cycle_backward()
    local size
    local i
    local temp_color
 
    size=u61_get_nb_items()

    temp_color=u61_get_item_color(0)

    i=0
    while i<size-1 do
        u61_set_item_color(i,u61_get_item_color(i+1))
        i=i+1
    end
        
    u61_set_item_color(size-1,temp_color)
end




-- color pattern: columns, lines diags of n squares with same colors ---------


function color_match_vertical(min_size)
    local i
    local x
    local y
    local size
    local found_size
    local found_x
    local found_y
    local last_color
    local found_color

    found_size=0
    x=u61_get_width()-1
    while x>=0 and found_size<min_size do
        size=1
        last_color=-1
        y=u61_get_height()-1
        while y>=0 do
            found_color=u61_get_square_color(x,y)
            if found_color>=0 and found_color==last_color then
                size=size+1
                if size>found_size then
                    found_size=size
                    found_x=x
                    found_y=y
                end
            else
                size=1
            end
            last_color=found_color
            y=y-1
        end
        x=x-1
    end

    if found_size>=min_size then
        i=found_size-1
        while i>=0 do
            u61_blow_up_square(found_x,found_y+i)
            i=i-1
        end
    end 
    
    return found_size 
end

function color_match_horizontal(min_size)
    local i
    local x
    local y
    local size
    local found_size
    local found_x
    local found_y
    local last_color
    local found_color

    found_size=0
    y=u61_get_height()-1
    while y>=0 and found_size<min_size do
        size=1
        last_color=-1
        x=u61_get_width()-1
        while x>=0 do
            found_color=u61_get_square_color(x,y)
            if found_color>=0 and found_color==last_color then
                size=size+1
                if size>found_size then
                    found_size=size
                    found_x=x
                    found_y=y
                end
            else
                size=1
            end
            last_color=found_color
            x=x-1
        end
        y=y-1
    end

    if found_size>=min_size then
        i=found_size-1
        while i>=0 do
            u61_blow_up_square(found_x+i,found_y)
            i=i-1
        end
    end 
    
    return found_size 
end

function color_match_diagonal1(min_size)
    local i
    local x
    local y
    local size
    local found_size
    local found_x
    local found_y
    local last_color
    local found_color

    found_size=0
    y=u61_get_height()+u61_get_width()-1
    while y>=0 and found_size<min_size do
        size=1
        last_color=-1
        x=u61_get_width()-1
        while x>=0 do
            found_color=u61_get_square_color(x,y-x)
            if found_color>=0 and found_color==last_color then
                size=size+1
                if size>found_size then
                    found_size=size
                    found_x=x
                    found_y=y-x
                end
            else
                size=1
            end
            last_color=found_color
            x=x-1
        end
        y=y-1
    end

    if found_size>=min_size then
        i=found_size-1
        while i>=0 do
            u61_blow_up_square(found_x+i,found_y-i)
            i=i-1
        end
    end 
    
    return found_size 
end

function color_match_diagonal2(min_size)
    local i
    local x
    local y
    local size
    local found_size
    local found_x
    local found_y
    local last_color
    local found_color

    found_size=0
    y=u61_get_height()-1
    while y>=-u61_get_width() and found_size<min_size do
        size=1
        last_color=-1
        x=u61_get_width()-1
        while x>=0 do
            found_color=u61_get_square_color(x,y+x)
            if found_color>=0 and found_color==last_color then
                size=size+1
                if size>found_size then
                    found_size=size
                    found_x=x
                    found_y=y+x
                end
            else
                size=1
            end
            last_color=found_color
            x=x-1
        end
        y=y-1
    end

    if found_size>=min_size then
        i=found_size-1
        while i>=0 do
            u61_blow_up_square(found_x+i,found_y+i)
            i=i-1
        end
    end 
    
    return found_size 
end

function color_match_pattern(match_count,min_size)
    local nb_found
    local found
    
    nb_found=0
    found=0

    if (nb_found<min_size) then
        nb_found=color_match_vertical(min_size)
    end
    if (nb_found<min_size) then
        nb_found=color_match_horizontal(min_size)
    end
    if (nb_found<min_size) then
        nb_found=color_match_diagonal1(min_size)
    end
    if (nb_found<min_size) then
        nb_found=color_match_diagonal2(min_size)
    end

    if nb_found>=min_size then
        u61_add_score((match_count+1)*1000
            *(nb_found-min_size+3)
            *(nb_found-min_size+3))
        found=1
    end

    return found
end


-- MORECOLORS curse: raises the number of colors from 6 to --------------------

ID_CURSE_MORECOLORS=9

function morecolors_do_curse(sent)
    if sent==0 then
        u61_send_curse(ID_CURSE_MORECOLORS)
    else
        u61_register_curse(ID_CURSE_MORECOLORS,300)
    end
end

function morecolors_get_nb()
    local nb_colors

    if u61_get_curse_age(ID_CURSE_MORECOLORS)>=0 then
        nb_colors=7
    else
        nb_colors=6
    end        

    return nb_colors
end
-- ANTIDOTE curse: gives add antidote-------------------------------

ID_CURSE_ANTIDOTE=0

function antidote_do_curse()
    u61_add_antidote()
end


-- CLEAR curse: clears the whole map -----------------------------------------

ID_CURSE_CLEAR=3

function clear_do_curse()
    utils_clear_map()
end


-- GOOFY curse: inverts the right & left keys --------------------------------

ID_CURSE_GOOFY=2

function goofy_do_curse(sent)
    if sent==0 then
        u61_send_curse(ID_CURSE_GOOFY)
    else
        u61_register_curse(ID_CURSE_GOOFY,120)
    end
end

function goofy_left()
    if (u61_get_curse_age(ID_CURSE_GOOFY)<0) then
        translation_x(-1)
    else
        translation_x(1)
    end    
end

function goofy_right()
    if (u61_get_curse_age(ID_CURSE_GOOFY)<0) then
        translation_x(1)
    else
        translation_x(-1)
    end    
end


-- WIND curse: forces the block to move sideways -------------------------

ID_CURSE_WIND=5
ID_GLOBAL_WIND_COUNTER=0
ID_GLOBAL_WIND_BLOCK_X=1

function wind_do_curse(sent)
    if sent==0 then
        u61_send_curse(ID_CURSE_WIND)
    else
        u61_register_curse(ID_CURSE_WIND,300)
        wind_reset_globals()
    end
end

function wind_time_callback()
    if u61_get_curse_age(ID_CURSE_WIND)>=0 then
        if u61_get_global(ID_GLOBAL_WIND_BLOCK_X)==u61_get_block_x() then
            if u61_get_time()-u61_get_global(ID_GLOBAL_WIND_COUNTER)>=100 then
                u61_set_block_x(u61_get_block_x()-1)
                wind_reset_globals()
            end
        else
            wind_reset_globals()
        end
    end
end

function wind_reset_globals()
    u61_set_global(ID_GLOBAL_WIND_COUNTER,u61_get_time())
    u61_set_global(ID_GLOBAL_WIND_BLOCK_X,u61_get_block_x())
end



-- MIXEDLINE curse: add a line with mixed colors ----------------------------

ID_CURSE_MIXEDLINE=8

function mixedline_do_curse(sent)
    local x
    local y
    local width
    local height
    local color

    if sent==0 then
        u61_send_curse(ID_CURSE_MIXEDLINE)
    else
        utils_shift_map_up()
    
        width=u61_get_width()
        height=u61_get_height() 

        x=0
        while x<width do
            color=mod(x+u61_get_time(),7)
            u61_set_square_color(x,height-1,color)
            x=x+1
        end
    end
end

