Problemas de herencias en tiempo de ejecución

Started by Danielo515, September 18, 2008, 02:59:07 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Danielo515

¿? Creia que tenia todo controlado en este código, pero el jodido fantasmilla me sigue dando errores en tiempo de ejecución por intentar acceder a su puñetero padre; He puesto como primera e indispensable condición en todas partes que la variable father sea true, pero no hay manera. Bien es cierto que no siempre da este error, sino que es en momentos críticos con muchos procesos dentro. Ya estoy algo rallado.
[code language="bennu"]Process fantasmilla_miniradar(int jugador,int lugar);
private
vehiculo_miniradar ident;
vehiculo_miniradar padre;
int explosion_delante;
begin
file=fpg_minijuego;
graph=1;
region=jugador;

//map_clear(0,graph,rgb(255,0,0));
padre=father;
repeat
alpha=miniradar_fantasmilla_alpha;            //LÍNEA DE DESARROLLADOR, PONERLA CON VALOR POSITIVO PORSIACA   
   frame;   
   
   switch(lugar)
   case 1:if(father)x=father.x+25;y=father.y;end end//case 1
   case 2:if(father)x=father.x;y=father.y-70;end end//case2        
   end
   
   ident=collision(type vehiculo_miniradar);//Aquí collisiona
   explosion_delante=collision(type explosiones_miniradar);
   
      /*Esta parte es para actuar dependiendo de si es el fantasmilla derecho o el superior*/
      switch(lugar)
      case 1: if(father) //esto es para que si no tiene padre no haga nada
         if(ident || collision(type valla_miniradar))padre.coche_derecho=1; //esto es para que no se adelanten o no se salgan del arcen
         else padre.coche_derecho=0;end//Este solo avisa de que hay un coche a la derecha
      end/*superif*/end//case 1
      case 2: if(father) //esto es para que si no tiene padre no haga nada
         if((ident &&(ident.region==padre.region)&& ident.velocidad_publica<padre.velocidad_publica) || explosion_delante)
            
            if(padre.coche_derecho==0 && padre.adelantando==0)//Este if tiene que ir aparte porque si no el else haría que se frenase el coche por ejemplo si ident=0 (no hay ninguno delante) o cualquiera de las otras condiciones fuera falsa
                 adelantar_miniradar(padre,jugador);
                 padre.adelantando=1; //así solo llama al adelantamiento una vez por cada coche, de lo contrario lo llamaba todo el rato que el fantasma estaba en contacto con el coche (adelantaba 3 o 4 veces por frame)       
              
               elif(padre.frenando==0 && !padre.adelantando);
                  frenada_miniradar(padre,ident.velocidad_publica,jugador);
                  padre.frenando=1;
               end //if
         end//if
      end/*superif*/end//case 2
      end//switch

until(y<miniradar_umbral_desaparicion[jugador])
signal(id,s_kill_tree); //esto es necesario para liquidar a los procesos frenada y adelantamiento, que intentando acceder a su abuelo cuando esta ya había muerto generaban muchos errores en tiempo de ejecución.
end[/code]

SplinterGU

exists(father)

y solo hace falta compararlo tras cada frame... luego, hasta el proximo frame, si la condicion dio true, entonces father existe...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Danielo515

Splinter, cuando mandas un signal s_kill_tree mata a toda la descendencia ¿no? y si no la tiene no da error en tiempo de ejecución no? Es que el puñetero proceso me sigue dando el mismo error.

Danielo515

Ahora que le he quitado una de las funcionalidades (en la que detectaba colisiones con un proceso que mataba a su padre y yo creo que su padre moría justo después de que el hiciera la comprobación de que existia, o algo así) el error me lo ha dado otro proceso, pero esta vez no era procedimiento 0 no activo, sino otro procedimiento. No se cual será, me imagino que su abuelo, ya que es el único al que accede. Pero ahora que pienso todo esto no tiene sentido! Si yo hago un s_kill_tree con el proceso que destrulle al padre de todos estos, ¿no debería haber problema no?

SplinterGU

descendencia si, ascendencia no... y los procesos huerfanos no recien signal, quizas debas hacer un signal por tipo de proceso... y puedas usar las caracteristicas de las funciones signal_action...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Danielo515

Creí que lo de signal action había sido un delirio de drumpi (no se porque me suena algo así). Si me lo explicas un poco intento hacerlo.
Pero cuando digo s_kill_tree me refiero que mato a sus hijos, nietos etc, y sin embargo me sigue dando errores de accesos a procesos no activos, antes eran el 0, ahora tienen identidad, pero es el miso error.
Me pasa solo con 2 procesos. El caso es que el padre antes de morir, mata a su hijo (el fantasma) y a sus nietos (posibles procesos frenada y aceleración)  ¿por que sigo teniendo este problema?
De postear el código ya lo hago mañana, que lo tendría que apañar y es largo.

SplinterGU

antes de acceder a un proceso, tenes que verificar que existe con exists... del exists hay informacion en el wiki...
con respecto a los signals, lo de drumpi si fue un delirio... pero bueno, mas alla de eso, esto de los sginals ya estaba en planes mucho antes del delirio mencionado :D...

signal_action sirve para decir como se comportara un proceso ante la accion de una señal. las posibles acciones son:

S_DFL - Signal default
S_IGN - Signal ignore

existen 2 formas o ambitos de uso de la funcion signal_action, una es local (afecta al proceso llamador) o remota (afecta a otro proceso), la sintaxis es la siguiente:

signal_action([process,] signal, action);

donde:

process,  puede ser un proceso especifico, procesos de un tipo especifico (usando TYPE) o todos los procesos (usando 0 o ALL_PROCESS)
signal, puede ser cualquiera de las señales ya conocidas (incluida las TREE).
action, cualquiera de las 2 mencionadas arriba (S_DFL o S_IGN).

A todo este sistema se agregan 8 nuevas señales, que sirven para forzar las señales independientemente de su action... podrian ser vistas como algo parecido a "signals dios", estas son:

S_KILL_FORCE       
S_WAKEUP_FORCE     
S_SLEEP_FORCE      
S_FREEZE_FORCE     
S_KILL_TREE_FORCE  
S_WAKEUP_TREE_FORCE
S_SLEEP_TREE_FORCE 
S_FREEZE_TREE_FORCE

cuyo valor son las signals conocidas + 50

-------------

quizas esto se aplique a tu necesidad actual o quizas no...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Danielo515

La verdad es que ahora no se me ocurre una aplicación inmediata, pero está bien saber estas cosas, cada día hay más funcines!
El caso es que me sigue dando el mismo problema, voy a poner el código del padre para que veas que, en teoría, es imposible que ninguno de sus hijos pueda acceder a un proceso inactivo.[code language="bennu"]/***********************************************************************************
***-------------------EL PUTO COCHE DE LOS WEBOS---------------------------------------------
*******************************************************************************************/
Process vehiculo_miniradar(int bonus,float velocidad,int jugador);
Private
   //float avance;
   //int fotos=1;   //valor máximo 1
   //int carril=0;   //por defecto irán por el carril 0
     //float slow_mo;
     //int detectado=1;
   
Begin
   file=fpg_minijuego;
   region=jugador;
   avance=miniradar_salida_coches[jugador];
   
   if(velocidad<600)
   graph=miniradar_graficos_coches[rand(0,2)];
   elif(velocidad<1000 && velocidad>600)
   graph=miniradar_graficos_coches[rand(2,6)];
   elif(velocidad>1000 && velocidad<2000)
   graph=miniradar_graficos_coches[rand(7,9)];
   elif(velocidad>2000)
   graph=miniradar_graficos_coches[rand(7,9)];
   end
   
    if(bonus)
    chivato_bonus_miniradar(bonus,jugador);
    end
   
   velocidad_publica=velocidad;
   fantasma1=fantasmilla_miniradar(jugador,2);
   fantasma2=fantasmilla_miniradar(jugador,1);
   
   
   /*AFECTADOS POR LA LLUVIA*/
         if(miniradar_lluvia_activa[jugador])
         velocidad_publica-=velocidad_publica*0.2; //le pasamos velocidad como parámetro ya que si le pasaramos velocidad pública, la frenada modifica esta variable y entraría en un bucle infinito.
         end
   
   // Elección de carril
   from i=0 to miniradar_num_carriles;//aqui comprueba si el carril vale 0 (libre)
      if(!miniradar_carril_ocupado[jugador]) //pero si el carril i vale 1(true), el carril está ocupado
         carril=i;
         break;                              //Nos vamos al otro carril
      else  //todos los carriles ocupados
         carril=0;                   
         avance+=100;
      end
   end
      
   miniradar_carril_ocupado[jugador][carril]++;//avisamos de que el carril está ocupado
   x=miniradar_carril[jugador][carril];        //y nos vamos al carril
                     
      
      repeat
   /*COMPORTAMIENTO EN CASO DE BONUS*/      
         /*AUTO*/
         if(miniradar_bonus[jugador]==1&& fotos>0 && y<miniradar_limite_inferior[jugador]-100 && (velocidad_publica*0.2)>miniradar_vel_permitida) //Esto es para que solo le puedas pillar una vez por pero que no pase nada si le das al flash antes de que este dentro de los límites Antes ocurria que el coche todavía no había aparecido en pantalla y sin embargo ya habías gastado la foto y no te permitía puntuar.
                                foto_miniradar(jugador);
                end
                
         /*SLOW MOTION*/         
         slow_mo=velocidad_publica/miniradar_slow_mo;//así la cámara lenta actua en tiempo real cuando se cambia la velocidad del coche
         
         if(miniradar_bonus[jugador]==2)avance-=(slow_mo/100);//si el jugador la camara lenta (bonus 2) va lento
         else avance-=(velocidad_publica/100);             //de lo contrario irá a velocidad normal
         end
         y=avance;
      
         
         if(miniradar_flashing[jugador] && fotos>0 && y<miniradar_limite_inferior[jugador]) //Esto es para que solo le puedas pillar una vez por pero que no pase nada si le das al flash antes de que este dentro de los límites Antes ocurria que el coche todavía no había aparecido en pantalla y sin embargo ya habías gastado la foto y no te permitía puntuar.
            fotos--;
            velocimetro_miniradar(x,y,velocidad_publica*0.2,jugador);
                end     
         
         
            
         if(y<=miniradar_altura_banda[jugador] && detectado>0)//esto es para el marcador de velocidad
         miniradar_vel_detect[jugador]=velocidad_publica*0.2;
         detectado--; //esto es para que una vez detectados dejen de mandar su valor al radar y lo dejen libre para otros
         end
         
                  
         frame;
      until(y<miniradar_umbral_desaparicion[jugador]);
       miniradar_carril_ocupado[jugador][carril]--;//libera el carril (vacio)
        signal(fantasma1,s_kill_tree);
        signal(fantasma2,s_kill_tree);
   //explosión de las naves o algo
End [/code]
Este es el supuesto padre y abuelo de todos, como ves, al final mata a los fantasmillas y toda su descendencia...

[code language="bennu"]Process fantasmilla_miniradar(int jugador,int lugar);
private
vehiculo_miniradar ident;
vehiculo_miniradar padre;
int explosion_delante;
begin
file=fpg_minijuego;
graph=1;
region=jugador;

//map_clear(0,graph,rgb(255,0,0));
padre=father;
repeat
alpha=miniradar_fantasmilla_alpha;            //LÍNEA DE DESARROLLADOR, PONERLA CON VALOR POSITIVO PORSIACA   
   frame;   
   
   switch(lugar)
   case 1:if(exists(father))x=father.x+25;y=father.y;end end//case 1
   case 2:if(exists(father))x=father.x;y=father.y-70;end end//case2        
   end
   
   ident=collision(type vehiculo_miniradar);//Aquí collisiona
   
   
      /*Esta parte es para actuar dependiendo de si es el fantasmilla derecho o el superior*/
      switch(lugar)
      case 1: if(exists(father)) //esto es para que si no tiene padre no haga nada
         if(ident || collision(type valla_miniradar))padre.coche_derecho=1; //esto es para que no se adelanten o no se salgan del arcen
         else padre.coche_derecho=0;end//Este solo avisa de que hay un coche a la derecha
      end/*superif*/end//case 1
      case 2: if(exists(father)) //esto es para que si no tiene padre no haga nada
         if((ident &&(ident.region==padre.region)&& ident.velocidad_publica<padre.velocidad_publica))
            
            if(padre.coche_derecho==0 && padre.adelantando==0)//Este if tiene que ir aparte porque si no el else haría que se frenase el coche por ejemplo si ident=0 (no hay ninguno delante) o cualquiera de las otras condiciones fuera falsa
                 adelantar_miniradar(padre,jugador);
                 padre.adelantando=1; //así solo llama al adelantamiento una vez por cada coche, de lo contrario lo llamaba todo el rato que el fantasma estaba en contacto con el coche (adelantaba 3 o 4 veces por frame)       
              
               elif(padre.frenando==0 && !padre.adelantando);
                  frenada_miniradar(padre,ident.velocidad_publica,jugador);
                  padre.frenando=1;
               end //if
         end//if
      end/*superif*/end//case 2
      end//switch

until(y<miniradar_umbral_desaparicion[jugador]|| !exists(father))

end[/code]

Este es el código de uno de los procesos que más errores da, junto con los de frenada y adelantamiento.
[code language="bennu"]

process adelantar_miniradar(int coche,int jugador)
private
vehiculo_miniradar coche_a_mover;
float vel_adelantamiento;

begin
coche_a_mover=coche;
vel_adelantamiento=coche_a_mover.velocidad_publica;
   
   from i= miniradar_carril[jugador][coche_a_mover.carril] to miniradar_carril[jugador][coche_a_mover.carril+1];
      coche_a_mover.x++;
          frame;
          if(!exists(father))signal(id,s_kill);end //esto es necesario, si no tiene padre quiere decir que el abuleo (curiosamente en la variable privada padre) va a morir pronto, y si intenta acceder a alguna de sus variables da error en tiempo de ejecución
   end // from
coche_a_mover.adelantando=0; //avisa de que ya ha adelantado
end //begin

Process frenada_miniradar(int coche,float velocidad_final,int jugador)
private
float reduccion_justa;
vehiculo_miniradar coche_a_frenar;
begin
coche_a_frenar=coche;
reduccion_justa=coche_a_frenar.velocidad_publica/4;


   repeat
      if(!exists(father))signal(id,s_kill);end //esto es necesario, si no tiene padre quiere decir que el abuleo (curiosamente en la variable privada padre) va a morir pronto, y si intenta acceder a alguna de sus variables da error en tiempo de ejecución
      coche_a_frenar.velocidad_publica--;
       mapa_frenadas_miniradar(jugador,coche_a_frenar.x-10,coche_a_frenar.y+20);
       mapa_frenadas_miniradar(jugador,coche_a_frenar.x+10,coche_a_frenar.y+20);
      frame;
   until(coche_a_frenar.velocidad_publica<=velocidad_final);
coche_a_frenar.frenando=0; //avisa de que ya ha frenado.
end[/code]

Te pongo esto por si hay alguna evidencia a primera vista de la que yo no me doy cuenta, pero si ves que hace falta ya te pongo una versión compilable.

SplinterGU

1) debes ser coherente con los chequeos, si usas father en el exists luego usa father no uses "padre", aunque arriba lo asignes al anterior...

2) tambien usas "ident" y ahi no chequeas por si existe, solo hace un "if (ident ...", ahi tambien tenes que poner el exists, lo mismo para cada uno de los procesos que accedes externamente...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Danielo515

splinter, uso father en el exists porque sé que se actualiza a cada frame, sin embarlo la varible padre no se actualiza a cada frame,aunque creo que con el exist eso no importa no? te dice en tiempo real si está vivo o no. claro lo hice antes de pensar en el funcionamiento de exist. Mediante father no puedo acceder a las variables públicas (que no locales) y por eso usaba las dos, porque creía que era importante que se actualizase a cada frame, ya veo que es indiferente.
¿donde debería poner el exist dentro del ident? creí que con que el ident tuviera un valor... espera! puede tener un valor y estar el proceso muerto! no reparé en eso.

Danielo515

Así sería correcto o resultaría redundante?
Lo voy a probar, pero a lo mejor estoy poniendo exists de mas XD

[code language="bennu"]/*-------------------------------------------------------------------------------*/
Process frenada_miniradar(int coche,float velocidad_final,int jugador)
private
float reduccion_justa;
vehiculo_miniradar coche_a_frenar;
begin
coche_a_frenar=coche;
reduccion_justa=coche_a_frenar.velocidad_publica/4;


   repeat
      if(!exists(coche_a_frenar))signal(id,s_kill);end //esto es necesario, si no tiene padre quiere decir que el abuleo (curiosamente en la variable privada padre) va a morir pronto, y si intenta acceder a alguna de sus variables da error en tiempo de ejecución
      coche_a_frenar.velocidad_publica--;
       mapa_frenadas_miniradar(jugador,coche_a_frenar.x-10,coche_a_frenar.y+20);
       mapa_frenadas_miniradar(jugador,coche_a_frenar.x+10,coche_a_frenar.y+20);
      frame;
   until(coche_a_frenar.velocidad_publica<=velocidad_final || !exists(coche_a_frenar));

if(exists(coche_a_frenar))coche_a_frenar.frenando=0;end//avisa de que ya ha frenado.
end


process adelantar_miniradar(int coche,int jugador)
private
vehiculo_miniradar coche_a_mover;
float vel_adelantamiento;

begin
coche_a_mover=coche;
if(exists(coche_a_mover))
   vel_adelantamiento=coche_a_mover.velocidad_publica;
   
   from i= miniradar_carril[jugador][coche_a_mover.carril] to miniradar_carril[jugador][coche_a_mover.carril+1];
      coche_a_mover.x++;
          frame;
          if(!exists(coche_a_mover))signal(id,s_kill);end //esto es necesario, si no tiene padre quiere decir que el abuleo (curiosamente en la variable privada padre) va a morir pronto, y si intenta acceder a alguna de sus variables da error en tiempo de ejecución
   end // from

coche_a_mover.adelantando=0; //avisa de que ya ha adelantado
end//if de existencia de padre
end //begin

/*---------------------------------------------------------------------------------*/

Process fantasmilla_miniradar(int jugador,int lugar);
private
vehiculo_miniradar ident;
vehiculo_miniradar padre;
int explosion_delante;
begin
file=fpg_minijuego;
graph=1;
region=jugador;

//map_clear(0,graph,rgb(255,0,0));
padre=father;
repeat
alpha=miniradar_fantasmilla_alpha;            //LÍNEA DE DESARROLLADOR, PONERLA CON VALOR POSITIVO PORSIACA   
   frame;   
   
   switch(lugar)
   case 1:if(exists(padre))x=padre.x+25;y=padre.y;end end//case 1
   case 2:if(exists(padre))x=padre.x;y=padre.y-70;end end//case2        
   end
   
   ident=collision(type vehiculo_miniradar);//Aquí collisiona
   
   
      /*Esta parte es para actuar dependiendo de si es el fantasmilla derecho o el superior*/
      switch(lugar)
      case 1: if(exists(padre)) //esto es para que si no tiene padre no haga nada
         if(ident || collision(type valla_miniradar))padre.coche_derecho=1; //esto es para que no se adelanten o no se salgan del arcen
         else padre.coche_derecho=0;end//Este solo avisa de que hay un coche a la derecha
      end/*superif*/end//case 1
      
      case 2: if(exists(padre) && exists(ident)) //esto es para que si no tiene padre no haga nada
         if((ident.region==padre.region)&& ident.velocidad_publica<padre.velocidad_publica))
            
            if(padre.coche_derecho==0 && padre.adelantando==0)//Este if tiene que ir aparte porque si no el else haría que se frenase el coche por ejemplo si ident=0 (no hay ninguno delante) o cualquiera de las otras condiciones fuera falsa
                 adelantar_miniradar(padre,jugador);
                 padre.adelantando=1; //así solo llama al adelantamiento una vez por cada coche, de lo contrario lo llamaba todo el rato que el fantasma estaba en contacto con el coche (adelantaba 3 o 4 veces por frame)       
              
               elif(padre.frenando==0 && !padre.adelantando);
                  frenada_miniradar(padre,ident.velocidad_publica,jugador);
                  padre.frenando=1;
               end //if
         end//if
      end/*superif*/end//case 2
      end//switch

until(y<miniradar_umbral_desaparicion[jugador]|| !exists(padre))

end[/code]

PD: SPLINTER, A PARTIR DE AHORA (NO PORQUE ANTES NO LO MERECIERAS) VAS A APARECER EN LOS CRÉDITOS DE TODOS MIS PATÉTICOS INTENTOS DE JUEGOS.

Danielo515

Por cierto, splinter, me asalta una duda acerca de las signals. Cuando un proceso recive una s_kill, ¿aborta en ese mismo momento? O ejecuta sus últimas líneas? por ejemplo, si justo antes del último end,  yo le pongo a un proceso un unload map, y luego le mando un s_kill ¿ejecuta esa última instrucción? ¿O se va a la porra?
Por cierto, creo que estoy a punto de encontrar una gran utilidad a tu sistema nuevo de señales.

SplinterGU

Los procesos se ejecutan 1 por vez hasta el frame... cuando un proceso recibe una señal y si esta es un kill, afecta en el momento... esto es por ejemplo, si me hago yo mismo un kill, o lo hace un proceso que acabo de llamar y todavia espero su retorno...

si vos queres que un proceso ejecute algo de codigo una vez muerto, deberias usar "on exit goto" u "onexit:", busca en el foro que hay documentacion al respecto.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Danielo515

Vale, es lo que me imaginaba, la funcion onexit ya la conocía de fenix 0.93, gracias, lo que yo ya no entiendo es porque esto me sigue dando errores de proceso tal o cual no activo, y siempre son los mismos dos procesos, adelantamiento y frenada, que por lo visto no saben morir cuando les toca, tengo ya exists(father) como condicion en todo, y aún así sigue dando el mismo error.

Si le puedes hechar un vistazo splinter, sin agobios por supuesto, te lo agradezco.

Venga un saludo.

PD: dios que dolor de cabeza.

SplinterGU

pero cuando te da? podes mostrar el log? lo compilaste con -g y ejecutaste con -d? ahi vas a ver exactamente donde te da el errror...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2