------------------------------------------------------------------------
-- Copyright (C) 2002 Daniel Heck
--
-- 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.
------------------------------------------------------------------------

----------------------
-- Global variables --
----------------------

level_width = 0
level_height = 0

oxyd_default_flavor = "b"       -- Default flavor for oxyd stones.
oxyd_count = 0
oxyd_current_color = 0

---------------
-- Functions --
---------------

function create_world(w, h)
    oxyd_default_flavor = "b"
    oxyd_count = 0
    oxyd_current_color = 0

    level_width = w
    level_height = h
    enigma.CreateWorld("", w, h)
end

function set_attrib(obj, key,val)
    if key == "name" then
        enigma.NameObject(obj, val)
    end
    enigma.SetAttrib(obj, key, val)
end

function set_attribs(obj, attrs)
    if not attrs then return end
    for key,val in attrs do
	set_attrib(obj, key, val)
    end
end

function make_object(name, attrs)
    local obj = enigma.MakeObject(name)
    set_attribs(obj, attrs)
    return obj
end


function set_floor(name, x, y, attrs)
    local obj = make_object(name, attrs)
    enigma.SetFloor(x,y,obj)
    return obj
end
function set_item(name, x, y, attrs)
    local obj = make_object(name, attrs)
    enigma.SetItem(x,y,obj)
    return obj
end
function set_stone(name, x,y, attrs)
    local obj=make_object(name, attrs)
    enigma.SetStone(x,y,obj)
    return obj
end

function fill_floor(name, x0,y0, w,h)
    for y=y0,y0+h-1 do
	for x=x0,x0+w-1 do
	    set_floor(name, x, y)
	end
    end
end

function draw_floor(name, xy0, xystep, n, attrs)
    local x,y = xy0[1],xy0[2]
    for i=1,n do
	set_floor(name, x, y, attrs)
	x = x+xystep[1]
	y = y+xystep[2]
    end
end
             
function draw_checkerboard_floor( name1, name2, x, y, w, h, attrs)
    for i=1,h do
        for j=1,w do
	    if mod( i,2) == mod( j,2) then
	        set_floor( name1, x+j-1 ,x+i-1, attrs)
	    else
	        set_floor( name2, x+j-1 ,x+i-1, attrs)
            end
	end
    end
end
             
function draw_items(name, xy0, xystep, n, attrs)
    local x,y = xy0[1],xy0[2]
    for i=1,n do
	set_item(name, x, y, attrs)
	x = x+xystep[1]
	y = y+xystep[2]
    end
end

function draw_stones(name, xy0, xystep, n, attrs)
    local x,y = xy0[1],xy0[2]
    for i=1,n do
	set_stone(name, x, y, attrs)
	x = x+xystep[1]
	y = y+xystep[2]
    end
end

function draw_border(stonename)
    draw_stones(stonename, {0,0}, {1,0}, level_width)
    draw_stones(stonename, {0,level_height-1},{1,0}, level_width)
    draw_stones(stonename, {0,0}, {0,1}, level_height)
    draw_stones(stonename, {level_width-1,0},{0,1}, level_height)
end

function set_stones(name, poslist, attrs)
    for i,xy in poslist do
	set_stone(name, xy[1], xy[2], attrs)
    end
end

function set_actor(name, x, y, attrs)
    local obj=make_object(name, attrs)
    enigma.SetActor(x, y,obj)
    return obj
end

---------------------------------------------
-- Creation of particular kinds of objects --
---------------------------------------------
function fakeoxyd(x,y) set_stone("st-fakeoxyd",x,y) end


-- Create an oxyd stone with the current default flavor.
function oxyd(x,y)
    set_stone("st-oxyd",x,y, {
                  flavor=oxyd_default_flavor, 
                  color=""..oxyd_current_color
              })
    oxyd_count = oxyd_count +1
    if oxyd_count == 2 then
        oxyd_count = 0
        oxyd_current_color = oxyd_current_color + 1
    end
end

-- Shuffle the colors of all oxyd stones in the current landscape.
function oxyd_shuffle()
    enigma.SendMessage(enigma.GetObjectTemplate("st-oxyd"), "shuffle", nil)
end

-- Close all oxyd stones in the current landscape
function oxyd_closeall()
    enigma.SendMessage(enigma.GetObjectTemplate("st-oxyd"), "closeall", nil)
end

function oneway(x,y,orient)
    return set_stone("st-oneway",x,y,{orientation=orient})
end
function laser(x,y,is_on,dir)
    return set_stone("st-laser",x,y,{on=is_on, dir=dir})
end

function mirrorp(x,y,movable, transp,orient)
    return set_stone("st-pmirror", x, y, {movable=movable, transparent=transp,
                         orientation=orient})
end
function mirror3(x,y,movable, transp, orient)
    return set_stone("st-3mirror", x, y, {movable=movable, transparent=transp,
                         orientation = orient})
end

PUZ_0000=1
PUZ_0001=2
PUZ_0010=3
PUZ_0011=4
PUZ_0100=5
PUZ_0101=6
PUZ_0110=7
PUZ_0111=8
PUZ_1000=9
PUZ_1001=10
PUZ_1010=11
PUZ_1011=12
PUZ_1100=13
PUZ_1101=14
PUZ_1110=15
PUZ_1111=16

function puzzle(x, y, conn)
    set_stone("st-puzzle", x,y, {connections=conn})
end
function switch(x,y,target,action)
    set_stone("st-switch", x,y, {target=target, action=action})
end

function abyss(x,y) set_floor("fl-abyss",x,y) end




-----------
-- ITEMS --
-----------
function hollow(x,y) set_item("it-hollow", x,y) end
function document(x,y,t) set_item("it-document", x, y, {text=t}) end
function hammer(x,y) set_item("it-hammer",x,y) end
function dynamite(x,y) set_item("it-dynamite",x,y) end
function bomb(x,y) set_item("it-blackbomb",x,y) end
function shogundot(x,y,size,attrs) 
    if attrs==nil then attrs={} end
    attrs.size = size
    set_item("it-shogun", x, y, attrs)
end
function keya(x,y) set_item("it-key", x,y, {keycode=1.0}) end
function keyb(x,y) set_item("it-key", x,y, {keycode=2.0}) end
function keyc(x,y) set_item("it-key", x,y, {keycode=3.0}) end

function shogundot1(x,y,attrs) shogundot(x,y,1,attrs) end
function shogundot2(x,y,attrs) shogundot(x,y,2,attrs) end
function shogundot3(x,y,attrs) shogundot(x,y,3,attrs) end

function doorh(x,y,attrs) 
    attrs = attrs or {}
    attrs.type="h"
    set_stone("st-door",x,y,attrs)
end
function doorv(x,y,attrs) 
    attrs = attrs or {}
    attrs.type="v"
    set_stone("st-door",x,y,attrs)
end



EAST = enigma.EAST
NORTH = enigma.NORTH
SOUTH = enigma.SOUTH
WEST = enigma.WEST
TRUE = 1
FALSE = 0


---------------
-- GRADIENTS --
---------------

SLOPE_S         = 1
SLOPE_N         = 2
SLOPE_E         = 3
SLOPE_W         = 4
SLOPE_LARGE_SE  = 5
SLOPE_LARGE_SW  = 6
SLOPE_LARGE_NE  = 7
SLOPE_LARGE_NW  = 8
SLOPE_SMALL_SE  = 9
SLOPE_SMALL_NE  = 10
SLOPE_SMALL_SW  = 11
SLOPE_SMALL_NW  = 12
SLOPE_S_FORCE_W = 13
SLOPE_N_FORCE_W = 14
SLOPE_S_FORCE_E = 15
SLOPE_N_FORCE_E = 16
SLOPE_E_FORCE_N = 17
SLOPE_W_FORCE_N = 18
SLOPE_E_FORCE_S = 19
SLOPE_W_FORCE_S = 20
FLAT_FORCE_S    = 21
FLAT_FORCE_N    = 22
FLAT_FORCE_E    = 23
FLAT_FORCE_W    = 24

function gradient( x, y, type )
    set_floor( "fl-gradient", x, y, {type=type} )
end


----------------------------------
-- Define some new object types --
----------------------------------
function def_stone(name, sound)
    enigma.DefineSimpleStone(name,sound or "st-stone")
end
function def_floor(name, frict, mfactor)
    enigma.DefineSimpleFloor(name, frict*2.5, mfactor)
end

def_stone("st-invisible")
def_stone("st-marble")
def_stone("st-rock1")
def_stone("st-rock2")
def_stone("st-rock3")
def_stone("st-greenbrown")
def_stone("st-brick")
def_stone("st-woven")

-- Floor(kind, friction, mousefactor)
def_floor("fl-dunes",      1.3,   1.0)
def_floor("fl-sand",       6.0,   2.0)
def_floor("fl-wood",       6.4,   2.0)
def_floor("fl-marble",     6.4,   2.0)
def_floor("fl-plank",      5.5,   2.0)
def_floor("fl-hay",        5.0,   1.5)
def_floor("fl-bluegreen",  6.0,   2.0)
def_floor("fl-bluegreenx", 0.4,   1.0)
def_floor("fl-gray",       5.0,   3.0)
def_floor("fl-space",      0.0,   0.0)
def_floor("fl-leaves",     5.0,   1.5)
def_floor("fl-inverse",    3.0,  -2.0)
def_floor("fl-metal",      3.0,   2.0)
def_floor("fl-normal",     4.0,   2.0)
def_floor("fl-rough",      7.0,   2.0)
def_floor("fl-brick",      4.0,   2.0)
--def_floor("fl-metal",      5.0,   3.0)
def_floor("fl-woven",      6.5,   3.0)
