--[[ Au Feu ! par Antoine Letouzey
     ameboure@yahoo.fr
     http://sexy-banane.mine.nu/~peter/jeux.php
]]

menu = nil
menu1 = nil
menu2 = nil
menu3 = nil
credits = nil
transition = nil

-- structures de données
-- feu = {idFen= [int], compteur = [int], hp = [int]}
-- perso = {idFen = [int], hp = [int], etat = [int], x [int], y [int]}
-- goutte d'eau = { x = [int], y = [int], v0_sin [float], v0_cos [float], t = [int], hp = [int] }
-- message = { x [int], y [int], typ = [int], t [int]}


-- chargement des images
Imfond = Image.load("datas/fond.png")
Imimmeuble = Image.load("datas/immeuble.png")
Imfeu = {}
Imfeu[0] = Image.load("datas/feu1.png")
Imfeu[1] = Image.load("datas/feu2.png")
Imperso = {}
Imperso[0] =  Image.load("datas/perso.png")
Imperso[1] = Image.load("datas/perso_echelle.png")
Imperso[2] = Image.load("datas/perso_echelle.png")
Imgoutte = Image.load("datas/goutte.png")
Imechelle = Image.load("datas/echelle.png")
Imdialogue = {}
Imdialogue[0] = Image.load("datas/help.png")
Imdialogue[1] = Image.load("datas/safe.png")
Imdialogue[2] = Image.load("datas/thanx.png")
Impause = Image.load("datas/pause.png")
Impausefond = Image.load("datas/menu.png")
Imgagne = Image.load("datas/gagne.png")
Imperdu = Image.load("datas/perdu.png")
n0 = Image.load("datas/00.png")
n1 = Image.load("datas/01.png")
n2 = Image.load("datas/02.png")
n3 = Image.load("datas/03.png")
n4 = Image.load("datas/04.png")
n5 = Image.load("datas/05.png")
n6 = Image.load("datas/06.png")
n7 = Image.load("datas/07.png")
n8 = Image.load("datas/08.png")
n9 = Image.load("datas/09.png")
n10 = Image.load("datas/10.png")
n11 = Image.load("datas/11.png")
n12 = Image.load("datas/12.png")
n13 = Image.load("datas/13.png")
n14 = Image.load("datas/14.png")
n15 = Image.load("datas/15.png")
n16 = Image.load("datas/16.png")
n17 = Image.load("datas/17.png")
n18 = Image.load("datas/18.png")
n19 = Image.load("datas/19.png")
n20 = Image.load("datas/20.png")

--chargement des sons
Music.playFile("datas/music.s3m", true)
Music.volume(128)

-- police
proportional = Font.createProportional()
proportional:setPixelSizes(0, 20)

     -- constantes --
RED = Color.new(255,0,0)
TAILLE = 15
TAILLEPERSO = 18
TAILLEFEU = 35
CONTINUER = true
GRAVITE = 0.12 -- l'axe des y est a l'envres
POS_X = 470
POS_Y = 110
-- les etats d'une fenetre
NBFEN = 13
OK = 0
BRULE = 1
PERSO = 2
PERSO_BRULE = 3

     -- Variables globales --
fenetres = {}
fenetres[1]  = {x=248, y=30, etat=OK}
fenetres[2]  = {x=251, y=149, etat=OK}
fenetres[3]  = {x=252, y=226, etat=OK}
fenetres[4]  = {x=287, y=70, etat=OK}
fenetres[5]  = {x=287, y=187, etat=OK}
fenetres[6]  = {x=324, y=31, etat=OK}
fenetres[7]  = {x=324, y=110, etat=OK}
fenetres[8]  = {x=324, y=225, etat=OK}
fenetres[9]  = {x=360, y=70, etat=OK}
fenetres[10] = {x=360, y=224, etat=OK}
fenetres[11] = {x=431, y=33, etat=OK}
fenetres[12] = {x=431, y=109, etat=OK}
fenetres[13] = {x=431, y=186, etat=OK}

personages = {}
feux = {}
gouttes = {}
messages = {}
echelle = {x = 300, y = 250}

nbMorts = 0;
nbSauves = 0;
statut = "aucun";

-----------------------------------------------------------
-----------------------------------------------------------
-----------  fonctions  -----------------------------------
-----------------------------------------------------------
-----------------------------------------------------------


-- donne un nb au pif entre d et f
function proba(d, f)
   math.randomseed(math.random(1, os.time())/100*math.pi)
   math.random(); math.random(1,math.pi)
   return math.random(d, f)
end 


-- affiche un feu
function print_feu(f)
 local sprite
 if f.compteur > 10 then sprite = 0
 else sprite = 1 end
 local decalage = (40 - f.hp) / 2
 screen:blit(fenetres[f.idFen].x - TAILLEFEU/2, fenetres[f.idFen].y - TAILLEFEU + 10 + decalage, Imfeu[sprite])
 f.compteur = f.compteur+1
 if f.compteur > 20 then f.compteur = 1 end
end

-- affiche un perso
function print_perso(p)
 if (p.etat == 0)
  then screen:blit(fenetres[p.idFen].x - TAILLEPERSO/2, fenetres[p.idFen].y - TAILLEPERSO + 3, Imperso[0])
  else screen:blit(p.x - 4, p.y, Imperso[p.etat])
 end
end

-- affiche une goute d'eau
function print_goutte(g)
 screen:blit(g.x,g.y,Imgoutte)
end

--affiche un message
function print_message(i,m)
 if m.t < 0 then table.remove(messages,i)
 else
  m.t = m.t -1
  screen:blit(m.x-10,m.y,Imdialogue[m.typ])
 end
end

-- ajoute un feu (on suppose que la fenetre ne brule pas deja)
function new_feu(fen,hp)
 if (fenetres[fen].etat == BRULE or fenetres[fen].etat == PERSO_BRULE) then return end
 if fenetres[fen].etat == PERSO then
  fenetres[fen].etat = PERSO_BRULE
  new_message(fenetres[fen].x + TAILLE/2, fenetres[fen].y - (TAILLE +20) , 0)
 else fenetres[fen].etat = BRULE
 end
 table.insert(feux,{idFen = fen, compteur = 0, hp = hp})
end

-- ajoute un perso (on suppose que la fenetre est libre)
function new_perso(fen,hp)
 fenetres[fen].etat = fenetres[fen].etat + PERSO
 table.insert(personages,{idFen = fen, hp = hp, etat = 0, x = 0, y = 0})
end

-- ajoute une goutte d'eau
function new_goutte(v, hp)
 local a = get_angle()
 if (a ~= 4) then
   table.insert(gouttes, {x = POS_X, y = POS_Y, v0_sin = v*(math.sin(a)), v0_cos = v*(math.cos(a)), t = 0, hp = hp})
 end
end

-- ajoute un message
function new_message(x, y, t)
 table.insert(messages, {x = x-10, y = y-5, typ = t, t = 30})
end

-- affichage complet
function affichage()
 screen:clear()
 screen:blit(0,0,Imfond)
 for i,v in ipairs(feux) do print_feu(v) end
 screen:blit(0,0,Imimmeuble)
 screen:blit(echelle.x,echelle.y, Imechelle)
 for i,v in ipairs(personages) do print_perso(v) end
 for i,v in ipairs(messages) do print_message(i,v) end
 for i,v in ipairs(gouttes) do print_goutte(v) end

 -- info du jeu
 if nbSauves == 0 then screen:blit(160, 62, n0) end
 if nbSauves == 1 then screen:blit(160, 62, n1) end
 if nbSauves == 2 then screen:blit(160, 62, n2) end
 if nbSauves == 3 then screen:blit(160, 62, n3) end
 if nbSauves == 4 then screen:blit(160, 62, n4) end
 if nbSauves == 5 then screen:blit(160, 62, n5) end
 if nbSauves == 6 then screen:blit(160, 62, n6) end
 if nbSauves == 7 then screen:blit(160, 62, n7) end
 if nbSauves == 8 then screen:blit(160, 62, n8) end
 if nbSauves == 9 then screen:blit(160, 62, n9) end
 if nbSauves == 10 then screen:blit(160, 62, n10) end
 if nbSauves == 11 then screen:blit(160, 62, n11) end
 if nbSauves == 12 then screen:blit(160, 62, n12) end
 if nbSauves == 13 then screen:blit(160, 62, n13) end
 if nbSauves == 14 then screen:blit(160, 62, n14) end
 if nbSauves == 15 then screen:blit(160, 62, n15) end
 if nbSauves == 16 then screen:blit(160, 62, n16) end
 if nbSauves == 17 then screen:blit(160, 62, n17) end
 if nbSauves == 18 then screen:blit(160, 62, n18) end
 if nbSauves == 19 then screen:blit(160, 62, n19) end
 if nbSauves == 20 then screen:blit(160, 62, n20) end

 if nbMorts == 0 then screen:blit(160, 175, n0) end
 if nbMorts == 1 then screen:blit(160, 175, n1) end
 if nbMorts == 2 then screen:blit(160, 175, n2) end
 if nbMorts == 3 then screen:blit(160, 175, n3) end
 if nbMorts == 4 then screen:blit(160, 175, n4) end
 if nbMorts == 5 then screen:blit(160, 175, n5) end
 if nbMorts == 6 then screen:blit(160, 175, n6) end
 if nbMorts == 7 then screen:blit(160, 175, n7) end
 if nbMorts == 8 then screen:blit(160, 175, n8) end
 if nbMorts == 9 then screen:blit(160, 175, n9) end
 if nbMorts == 10 then screen:blit(160, 175, n10) end
 if nbMorts == 11 then screen:blit(160, 175, n11) end
 if nbMorts == 12 then screen:blit(160, 175, n12) end
 if nbMorts == 13 then screen:blit(160, 175, n13) end
 if nbMorts == 14 then screen:blit(160, 175, n14) end
 if nbMorts == 15 then screen:blit(160, 175, n15) end
 if nbMorts == 16 then screen:blit(160, 175, n16) end
 if nbMorts == 17 then screen:blit(160, 175, n17) end
 if nbMorts == 18 then screen:blit(160, 175, n18) end
 if nbMorts == 19 then screen:blit(160, 175, n19) end
 if nbMorts == 20 then screen:blit(160, 175, n20) end
end

-- donne l'angle formé par le pad analogique
function get_angle()
 local pad = Controls.read()
 local x = pad:analogX()
 local y = pad:analogY()

 -- calcul de l'angle
 if (x < 0) then
  local a = math.asin(y/128)
  return -(math.pi -a)
 else return 4
 end
end

-- fais bouger les gouttes
function bouge_gouttes()
 for i,g in ipairs(gouttes) do
  g.t = g.t+1
  g.x = (g.v0_cos * g.t) + POS_X
  g.y = -(0.5 * -GRAVITE * g.t * g.t +  g.v0_sin * g.t) + POS_Y
  -- verif que la goutte est pas sortie
  if (g.x < 0 or g.x > 470 or g.y < 0 or g.y > 272) then
   table.remove(gouttes,i)
  end -- fin du if
 end -- fin du for
end

-- gere les interraction gouttes / feux
function eteint()
 for i,g in ipairs(gouttes) do
  for j, f in ipairs(feux) do
   local xf = fenetres[f.idFen].x
   local yf = fenetres[f.idFen].y
   -- regarde si la goutte est sur le feu
   if ((g.x+3 > xf - TAILLEFEU/2) and (g.x-3 < xf + TAILLEFEU/2) and (g.y+3 > yf - TAILLEFEU) and (g.y-3 < yf)) then
     f.hp = f.hp - g.hp
     if (f.hp <= 0) then
      if fenetres[f.idFen].etat == BRULE then fenetres[f.idFen].etat = OK
      else
        fenetres[f.idFen].etat = PERSO
        new_message(fenetres[f.idFen].x + TAILLE/2, fenetres[f.idFen].y - (TAILLE +20) , 1)
      end
      table.remove(feux, j)
     end
     table.remove(gouttes, i)
     break
   end
  end -- fin du for (feux)
 end -- fin du for (gouttes)
end


-- fait bruler les persos
function persoBrule()
 for i, p in ipairs(personages) do
  if (fenetres[p.idFen].etat == PERSO_BRULE) then
   p.hp = p.hp - 1
   if (p.hp < 0) then
    table.remove(personages,i)
    nbMorts = nbMorts+1
    fenetres[p.idFen].etat = BRULE
   end
  end
 end
end

-- ajoute des feux dans les fenetres libres
function ajout_feu()
 for i = 1 , NBFEN, 1 do
  if (fenetres[i].etat == OK or fenetres[i].etat == PERSO) then
   local prob = proba(0,5)
   if (prob==1) then new_feu(i,40) end
  end
 end
end

-- ajoute des perso dans les fenetres libres
function ajout_perso()
 for i = 1 , NBFEN, 1 do
  if (fenetres[i].etat == OK) then
   local prob = proba(0,5)
   if (prob==1) then new_perso(i,200) end
  end
 end
end

-- donne le numero de la fenetre dans laquelle se trouve l'echelle -1 sinon
function positionEchelle()
 local res = -1
 for i, f in ipairs(fenetres) do
   if (echelle.x > f.x -10 and echelle.x < f.x + 2 and echelle.y > f.y -10 and echelle.y < f.y) then
     res =  i
     break
    end
 end
 return res
end

-- change l'etat d'un perso
function sauvePerso()
  for i, p in ipairs(personages) do
    local f = positionEchelle()
    if (f == p.idFen and fenetres[p.idFen].etat == PERSO) then
     fenetres[f].etat = OK
     p.etat = 1
     p.x = echelle.x 
     p.y = echelle.y
     nbSauves = nbSauves +1
     return
    end
  end
end

-- bouge l'echelle
function bougeEchelle()
 pad = Controls.read()
 local decx = 0
 local decy = 0
 if (pad:square() and echelle.x > 225) then
  echelle.x = echelle.x - 2
  decx = decx - 2
 end
 if (pad:circle() and echelle.x < 470) then
  echelle.x = echelle.x + 2
  decx = decx + 2
 end
 if (pad:triangle() and echelle.y > 0) then
  echelle.y = echelle.y - 2
  decy = decy - 2
 end
 if (pad:cross() and echelle.y < 272) then
  echelle.y = echelle.y + 2
  decy = decy + 2
 end
 -- repercute le mvt sur les perso sur l'echelle
 for i, p in ipairs(personages) do
  if (p.etat == 1 or p.etat == 2) then
   p.x = p.x + decx 
   p.y = p.y + decy 
  end
 end
end

-- fais bouger les perso en mvt
function bougePerso()
 for i,p in ipairs(personages) do
  -- perso sur l'echelle
  if(p.etat == 2) then
   p.y = p.y + 2
   if(p.y > 272) then table.remove(personages, i) end
  end
  -- perso sur l'echelle
  if(p.etat == 1) then
   p.y = p.y + 2
   if(p.y > 255 ) then
    p.etat = 2
    p.y = 250
    new_message(p.x, p.y, 2)
   end
  end
 end
end

-- pause
function pause() 
while true do
screen:clear()
screen:blit(0, 0, Impausefond)
screen:blit(128, 62, Impause) 
pad = Controls.read() 
if pad:cross() then 
frommenu=false  
screen.waitVblankStart() 
screen:flip() 
break 
end  
if pad:triangle() then
Music.stop() 
dofile "menu.lua"
break
end 
screen.waitVblankStart() 
screen:flip() 
end
end

-----------------------------------------
----------  tests   ---------------------
-----------------------------------------
for i = 1, NBFEN, 2 do
 new_feu(i, 40)
end

for i = 2, NBFEN, 2 do
 new_perso(i, 200)
end

cpt = 0

while CONTINUER == true do
 pad = Controls.read()
 if (pad:l() or pad:r()) then new_goutte(14,5) end
 bougeEchelle()
 bougePerso()
 sauvePerso()
 bouge_gouttes()
 eteint()
 persoBrule()
 if (cpt == 0) then
  ajout_feu()
  ajout_perso()
 end
 
 affichage()
 screen.flip()
 screen.waitVblankStart()
 if pad:select() then screen:save("shot.png") end
 if pad:start() then 
 pause()
 end
 cpt = cpt+1
 if (cpt > 100) then cpt = 0 end

if nbSauves == 20 then 
statut = "victoire"
CONTINUER = false
end

if nbMorts == 20 then 
statut = "defaite"
CONTINUER = false
end

end --fin du while

while CONTINUER == false do
screen:clear()
screen:blit(0, 0, Imfond)
pad = Controls.read()

if (statut == "victoire") then
screen:blit(100, 10, Imgagne)
screen.waitVblankStart(20)
 if pad:cross() then
 Music.stop()
 dofile("menu.lua")
 end
screen.flip()
screen.waitVblankStart()
end
if (statut == "defaite") then
screen:blit(100, 10, Imperdu)
screen.waitVblankStart(20)
 if pad:cross() then
 Music.stop()
 dofile("menu.lua")
 end
screen.flip()
end

end
