# -*- coding: latin-1 -*-
# Balazar Brothers
# Copyright (C) 2003-2006 Jean-Baptiste LAMY
#
# 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

import random, math
import tofu, soya, soya.tofu4soya

import balazar_brothers


LAND_SIZE  = 33
LAND_SCALE = 2.5
LAND_DIM   = LAND_SCALE * LAND_SIZE

    
def random_land(level,
                default_min_y = 0.18, default_max_y = 0.23,
                nb_max = 0.0015,
                pic_proba = 0.1, plateau_proba = 0.25, colline_proba = 0.25, cratere1_proba = 0.1, cratere2_proba = 0.1, monticule_proba = 0.1, termitiere_proba = 0.1, 
                ):
  
  land = soya.Land(None, LAND_SIZE)
  land.texture_factor = 0.25
  
  proba = pic_proba + plateau_proba + colline_proba + cratere1_proba + cratere2_proba + monticule_proba + termitiere_proba
  pic_proba        += 0
  plateau_proba    += pic_proba
  colline_proba    += plateau_proba
  cratere1_proba   += colline_proba
  cratere2_proba   += cratere1_proba
  monticule_proba  += cratere2_proba
  termitiere_proba += monticule_proba
  
  # Default height
  for i in range(LAND_SIZE):
    for j in range(LAND_SIZE):
      land.set_height(i, j, random.uniform(default_min_y, default_max_y))
      
  for n in range(int(random.uniform(0.001, nb_max) * LAND_SIZE * LAND_SIZE)):
    t = random.random() * proba
    x = random.randrange(LAND_SIZE)
    y = random.randrange(LAND_SIZE)
    if   t < pic_proba:
      r = random.randrange(5, 20)
      h = random.uniform(0.5, 2.5)
      
      for i in range(max(0, x - r), min(LAND_SIZE - 1, x + r)):
        for j in range(max(0, y - r), min(LAND_SIZE - 1, y + r)):
          d = (r - math.sqrt((i - x) * (i - x) + (j - y) * (j - y))) / float(r)
          if d > 0.0:
            d = d * d
            land.set_height(i, j, min(1.0, d * h + land.get_height(i, j)))
            
    elif t < plateau_proba:
      r1 = random.randrange(10, 20)
      r2 = random.randrange(r1 + 5, 40)
      h  = random.uniform(0.05, 0.3)
      
      for i in range(max(0, x - r2), min(LAND_SIZE - 1, x + r2)):
        for j in range(max(0, y - r2), min(LAND_SIZE - 1, y + r2)):
          d = (r2 - math.sqrt((i - x) * (i - x) + (j - y) * (j - y))) / float(r2 - r1)
          if d > 1.0: d = 1.0
          if d > 0.0:
            d = 0.5 - (math.cos(d * math.pi) / 2.0)
            land.set_height(i, j, min(1.0, d * h + land.get_height(i, j)))
            
    elif t < colline_proba:
      r = random.randrange(5, 35)
      h = random.uniform(0.1, 0.4)
      
      for i in range(max(0, x - r), min(LAND_SIZE - 1, x + r)):
        for j in range(max(0, y - r), min(LAND_SIZE - 1, y + r)):
          d = (r - math.sqrt((i - x) * (i - x) + (j - y) * (j - y))) / float(r)
          if d > 0.0:
            d = 0.5 - (math.cos(d * math.pi) / 2.0)
            land.set_height(i, j, min(1.0, d * h + land.get_height(i, j)))
            
    elif t < cratere1_proba:
      r = random.randrange(15, 20)
      h = random.uniform(0.1, 0.1)
      
      for i in range(max(0, x - r), min(LAND_SIZE - 1, x + r)):
        for j in range(max(0, y - r), min(LAND_SIZE - 1, y + r)):
          d = (r - math.sqrt((i - x) * (i - x) + (j - y) * (j - y))) / float(r)
          if d > 0.0:
            d = (math.sin(d * math.pi) / 2.0) + 0.5
            land.set_height(i, j, min(1.0, d * h + land.get_height(i, j)))
            
    elif t < cratere2_proba:
      r = random.randrange(15, 20)
      h = random.uniform(0.1, 0.1)
      
      for i in range(max(0, x - r), min(LAND_SIZE - 1, x + r)):
        for j in range(max(0, y - r), min(LAND_SIZE - 1, y + r)):
          d = (r - math.sqrt((i - x) * (i - x) + (j - y) * (j - y))) / float(r)
          if d > 0.0:
            d = (math.cos(d * math.pi) / 2.0) + 0.5
            land.set_height(i, j, min(1.0, d * h + land.get_height(i, j)))
            
    elif t < monticule_proba:
      r = random.randrange(5, 20)
      h = random.uniform(0.5, 1.0)
      
      for i in range(max(0, x - r), min(LAND_SIZE - 1, x + r)):
        for j in range(max(0, y - r), min(LAND_SIZE - 1, y + r)):
          d = (r - math.sqrt((i - x) * (i - x) + (j - y) * (j - y))) / float(r)
          if d > 0.0:
            d = math.sqrt(d)
            land.set_height(i, j, min(1.0, d * h + land.get_height(i, j)))
            
    else:
      # Termitière conique XXX une texture spéciale ?
      r = random.randrange(5, 15)
      h = random.uniform(0.1, 0.5)
      
      for i in range(max(0, x - r), min(LAND_SIZE - 1, x + r)):
        for j in range(max(0, y - r), min(LAND_SIZE - 1, y + r)):
          d = (r - math.sqrt((i - x) * (i - x) + (j - y) * (j - y))) / float(r)
          if d > 0.0:
            land.set_height(i, j, min(1.0, d * h + land.get_height(i, j)))
            
            
  smooth_land       (level, land)
  random_land_border(level, land)
  end_land          (level, land)
  land.y = -30.0
  return land
  
def smooth_land(level, land, nb = 2):
  for k in range(nb):
    smoothed = [0.0] * (LAND_SIZE * LAND_SIZE)
    for i in range(1, LAND_SIZE - 1):
      for j in range(1, LAND_SIZE - 1):
        smoothed[i + LAND_SIZE * j] = (land.get_height(i, j) + land.get_height(i - 1, j) + land.get_height(i, j - 1) + land.get_height(i + 1, j) + land.get_height(i, j + 1)) / 5.0
    for i in range(1, LAND_SIZE - 1):
      for j in range(1, LAND_SIZE - 1):
        land.set_height(i, j, smoothed[i + LAND_SIZE * j])
        
def random_land_border(level, land):
  out_of_map_vertex_options = (1, 1)
  
  fall_length  = 2
  afall_length = 0
  for i in range(LAND_SIZE):
    for j in range(fall_length):
      land.set_vertex_option(i, j, *out_of_map_vertex_options)
      #land.set_vertex_color(i, j, (0.0, 0.0, 0.0, 0.0))
      land.set_height(i, j, 0.0)
    land.set_height(i, j + 1, 0.92 * land.get_height(i, j + 1))
    if i % 2:
      fall_length = max(1, fall_length + afall_length)
      if (fall_length == 1) and (afall_length == -1): afall_length = 0
      else: afall_length = max(-1, min(1, afall_length + random.randint(-1, 1)))
      
  fall_length  = 2
  afall_length = 0
  for i in range(LAND_SIZE):
    for j in range(LAND_SIZE - 1, LAND_SIZE - fall_length - 1, -1):
      land.set_vertex_option(i, j, *out_of_map_vertex_options)
      #land.set_vertex_color(i, j, (0.0, 0.0, 0.0, 0.0))
      land.set_height(i, j, 0.0)
    land.set_height(i, j - 1, 0.92 * land.get_height(i, j - 1))
    if i % 2:
      fall_length = max(1, fall_length + afall_length)
      if (fall_length == 1) and (afall_length == -1): afall_length = 0
      else: afall_length = max(-1, min(1, afall_length + random.randint(-1, 1)))

  fall_length  = 2
  afall_length = 0
  for j in range(LAND_SIZE):
    for i in range(fall_length):
      land.set_vertex_option(i, j, *out_of_map_vertex_options)
      #land.set_vertex_color(i, j, (0.0, 0.0, 0.0, 0.0))
      land.set_height(i, j, 0.0)
    land.set_height(i + 1, j, 0.92 * land.get_height(i + 1, j))
    if j % 2:
      fall_length = max(1, fall_length + afall_length)
      if (fall_length == 1) and (afall_length == -1): afall_length = 0
      else: afall_length = max(-1, min(1, afall_length + random.randint(-1, 1)))
      
  fall_length  = 2
  afall_length = 0
  for j in range(LAND_SIZE):
    for i in range(LAND_SIZE - 1, LAND_SIZE - fall_length - 1, -1):
      land.set_vertex_option(i, j, *out_of_map_vertex_options)
      #land.set_vertex_color(i, j, (0.0, 0.0, 0.0, 0.0))
      land.set_height(i, j, 0.0)
    land.set_height(i - 1, j, 0.92 * land.get_height(i - 1, j))
    if j % 2:
      fall_length = max(1, fall_length + afall_length)
      if (fall_length == 1) and (afall_length == -1): afall_length = 0
      else: afall_length = max(-1, min(1, afall_length + random.randint(-1, 1)))


def end_land(level, land, height = 50.0):
  land.multiply_height(height)
  land.scale_factor = LAND_SCALE
  land.map_size = 8
  land.split_factor = 4.0
  
  level.static_part.add(land)


def add_flower(level, land, nb = 40):
  grass2 = soya.Material.get("grass3")
  for i in range(nb):
    x = random.randrange(LAND_SIZE)
    y = random.randrange(LAND_SIZE)
    r = random.randint(1, 3)
    
    for i in range(max(0, x - r), min(LAND_SIZE - 1, x + r)):
      for j in range(max(0, y - r), min(LAND_SIZE - 1, y + r)):
        d = (r - math.sqrt((i - x) * (i - x) + (j - y) * (j - y))) / float(r)
        if (d >= 0.0) and land.get_height(i, j) < 30:
          land.set_material(i, j, grass2)
  

  



    
