// Este módulo almacena mejoras al parser de VSintac, que he hecho para ASTRAL. // AdyPsis(loc): este añadido hace aparecer junto con la descripción, // si hay PSIs en las habitaciones inmediatamente cercanas, y en todas las direcciones // posibles. (Chequea las direcciones de la localidad). Se le pasa como // parámetro la localidad a partir de la cual buscar. Sub AdyPsis(loc) declare(locady) declare(conex) declare(conexiones) declare(numconex) declare(arraypsi) declare(i) conexiones:=LOC[loc].Conexiones() // almacena el verbo de las direcciones numconex:=ArrayLen(conexiones) // y el numero de loc donde conectan. if (numconex<>0) then i:=1 while (i<=(numconex-1)) conex:=ArrayItem(conexiones,i) // en el array, la dirección viene antes... locady:=ArrayItem(conexiones,i+1) // que la localidad de destino. if (locady<>0)&(loc<>locady) then // mira a través de todas las conexiones salvo las que sean a una misma. Pero esto luego habría que ampliarlo a puertas cerradas tb. if LOC[locady].Marabunta=TRUE then print("¡Cuidado!: La gran marabunta de zombies se acerca por el "+ LCase(conex)+". ") else arraypsi:=ListaPsis(locady,FALSE) // Esto devuelve un array de los distintos tipos de PSIS que hay pa imprimir. if arraypsi<>"" then // si está vacío es que no había ninguno print("En el " + LCase(conex) + " ves " + arrayformat(arraypsi, ", ", " y ", ". ", "")) endif endif endif i:=i+2 // +2 pues la siguiente dirección está 2 índices más arriba. loop EndIf return // ArrayRemove(array,posicion): Borra el elemento en posición del array. sub ArrayRemove(array,posicion) declare(ret) declare(i) declare(j) declare(elemento) j:=1 for i:=1 to ArrayLen(array) IF (i<>posicion) then elemento:=ArrayItem(array,i) ret:=ArrayInsert(ret,j,elemento) j:=j+1 endif next return ret // ArrayRemoveItem(array,item): Devuelve un array borrando todas las ocurrencias de item en array. sub ArrayRemoveItem(array,item) declare(pos) pos:=InArray(array,item) while (pos<>0) array:=ArrayRemove(array,pos) pos:=InArray(array,item) loop return array // Blandir(). Esto sirve para elegir un objeto como arma al atacar sub Blandir() declare(obj) declare(lista) obj:=NombreCompleto(parsenombre1,parseadjetivo1) if obj="" then print("¿Que quieres blandir?"+CR) else lista:=Search(obj,"",2) if ArrayLen(lista)=0 then print("No tienes eso."+CR) else PSI[PSIJugador].Arma_Preferida:=ArrayItem(lista,1) print("Agarras con firmeza "+OBJ[ArrayItem(lista,1)].DescCorta+", dispuesto a estrellarlo contra el zombie más cercano."+CR) endif endif return // Empujar(), acción de empujar, que aqui se aplica como un ataque a un PSI. sub Empujar() declare(obj) declare(psi) declare(lista) psi:=FALSE obj:=NombreCompleto(parsenombre1,parseadjetivo1) if obj="" then if (ArrayLen(PSI[PSIJugador].Atacante)>0) then // esto se supone que pone como objetivo uno de los zombies atacantes obj:=ArrayItem(PSI[PSIJugador].Atacante,1) else print("¿Que quieres empujar?. No lo veo por ningún lado."+CR) return endif endif // buscamos el objeto que queremos empujar (debe estar presente) lista:=Search(obj,"",0) // si no encontramos el objeto probamos con un PSI If ArrayLen(lista)<1 Then lista:=Search(obj,"",3) psi:=TRUE EndIf If psi Then // Si empujamos a un PSI Select ArrayLen(lista) Case 0 print("No hay ningún "+LCase(obj)+" cerca."+CR) Case 1 PSIAtaca(PSIJugador,"empujar",ArrayItem(lista,1),"") Case * print("(empujas a uno de ellos al azar)"+CR) obj:=ArrayItem(lista,Random(1,ArrayLen(lista))) PSIAtaca(PSIJugador,"empujar",obj,"") PSI[PSIJugador].fuerza:=PSI[PSIJugador].fuerza-17 EndSelect endif if not(psi) then // Si empujamos un objeto Select ArrayLen(lista) Case 0 print("No ves nada que empujar aqui."+CR) Case 1 print("De nada servirá empujar eso."+CR) Case * print("¿Qué "+obj+" quieres empujar?."+CR) EndSelect EndIf return // EstadoJugador(verbose), imprime por pantalla el estado físico en el que se encuentra el // protagonista. Verbose hace que diga sin más guevos el estado. sub EstadoJugador(verbose) declare(cans_act) // nivel de cansancio calculado ahora. declare(fuerza) declare(texto) declare(heridas) // CANSANCIO fuerza:=PSI[PSIJugador].fuerza if (fuerza<=100)&(fuerza>75) then cans_act:=0 endif if (fuerza<=75)&(fuerza>50) then cans_act:=1 endif if (fuerza<=50)&(fuerza>25) then cans_act:=2 endif if (fuerza<=25)&(fuerza>0) then cans_act:=3 endif if fuerza<=0 then cans_act:=4 endif if (cansancio<>cans_act)|(verbose) then // si no son iguales, veremos como ha cambiado el cansancio y se imprimirá // un mensaje acorde con dicha evolución. if (cans_act=15 then print("El suelo está completamente manchado aqui y allá de grandes charcos de sangre. Los adoquines carmesíes están resbaladizos, pues hay que añadirle trozos de carne y vísceras que están diseminados por todo el suelo") else if gore>=8 then print("Grandes charcos de sangre mezclados con trozos de carne y vísceras, yacen aqui") else if gore>=4 then print("Hay diversos charcos de sangre fresca en el suelo") else if gore>=1 then print("El suelo está manchado con un poco de sangre") endif endif endif endif // CABEZAS gore:=LOC[loc].gore_cabeza if gore=1 then print(". También puedes ver que una cabeza cercenada; te observa desde el suelo") endif if gore=2 then print(". Aqui hay un par de cabezas cercenadas") endif if gore>2 then print(". Y ves "+LOC[loc].gore_cabeza+" cabezas") Endif // CUERPOS gore:=LOC[loc].gore_cuerpo if gore=1 then print(", junto al cuerpo inanimado de un zombie, que yace aqui") endif if gore=2 then print(", junto a un par de cadáveres que yacen aqui") endif if gore>2 then if LOC[loc].gore_cuerpo>=5 then print(". Hay un montón de cuerpos, algunos de ellos con las vísceras fuera del vientre, diseminados por todo el suelo alrededor ") else print(". Puedes distinguir "+LOC[loc].gore_cuerpo+" cuerpos muertos tirados en el suelo") endif Endif // Miembros amputados... if (LOC[loc].gore_brazo>3)&(LOC[loc].gore_pierna>2) then // esto es si hay mucha 'chicha' en el suelo. print(", y varios miembros amputados o cercenados están desparramados... ") Select LOC[loc].gore_pierna Case 0 Case 1 print(", una pierna") Case 2 print(", un par de piernas") Case * print(", "+LOC[loc].gore_pierna+" piernas") EndSelect print("y ") Select LOC[loc].gore_brazo Case 0 Case 1 print(", un brazo") Case 2 print(", un par de brazos") Case * print(", LOC[loc].gore_brazo+" brazos") EndSelect print(". ") else // si hay poca chicha gore:=LOC[loc].gore_pierna if gore=1 then print(". Y hay una pierna rasgada de raiz") endif if gore=2 then print(". Aqui hay un par de piernas") endif if gore>2 then print(". También hay diseminadas "+LOC[loc].gore_pierna+" piernas desgarradas") endif gore:=LOC[loc].gore_brazo if gore=1 then print("; y un brazo ensangrentado") endif if gore=2 then print("; y un par de brazos desmembrados") endif if gore>2 then print("; y "+LOC[loc].gore_brazo+" brazos desparramados sobre los adoquines rojos de sangre") Endif EndIf if LOC[loc].gore_sangre>0 then If Random(1,2)<=1 then print("; el total da un aspecto muy macabro al lugar."+CR) else print(". "+CR) endif endif return // ListaObjetos(loc): Esto imprime en pantala los objetos de la localidad que // se le pasa como parámetro. Está extraido de DescriciónLocalidad directamente, // pues me parece mejor ponerlo aparte. sub ListaObjetos(loc) declare(objetos) declare(numobjetos) declare(i) declare(obj) declare(objs_escenario) declare(c) declare(lista) objs_escenario:=FALSE objetos:=LOC[loc].Objetos() numobjetos:=ArrayLen(objetos) If numobjetos>0 Then // construimos la lista de objetos separados por comas (,) lista:="" For i:=1 To numobjetos obj:=ArrayItem(objetos,i) // si es un objeto de escenario lo incluye // en la descripción de la localidad If (OBJ[obj].Escenario) & Not(OBJ[obj].Invisible) Then If Not(objs_escenario) Then // entre el texto de la localidad y los objetos // de escenario, hacemos una salto de línea Print(CR) objs_escenario:=TRUE EndIf Print(OBJ[obj].DescCorta + ". ") Else // sólo lo incluye si está visible If Not(OBJ[obj].Invisible) Then c:=Articulo(obj,0) + OBJ[obj].DescCorta lista:=ArrayInsert(lista,ArrayLen(lista)+1,c) EndIf EndIf Next If ArrayLen(lista)>0 Then If objs_escenario Then // hacemos un salto de línea si hay objetos de escenario Print(CR) // indicamos que ya se ha hecho el salto de línea objs_escenario:=FALSE EndIf Print("También ves: " + ArrayFormat(lista,", "," y ",".","") + CR) EndIf EndIf If objs_escenario Then // hacemos un salto de línea si hay objetos de escenario Print(CR) // indicamos que ya se ha hecho el salto de línea objs_escenario:=FALSE EndIf return // ListaPsis(loc,verbose) // esto devuelve las descripciones de Psis de cualquier habitación en general (loc) // en un array (lista), listo para imprimir. // solo incluye en el array los que están visible, pues su finalidad es imprimirlo // después. // Si el array devuelto es vacio ("") quiere decir que no habia Psis visibles en esa // localidad. // Tambien ante Psis con nombres iguales, imprimira un mensaje sobre la // multiplicidad de Psis iguales. Tb este mensaje depende de VERBOSE, que si es TRUE, // dirá por ejemplo: Aqui hay 2 zombies (un zombie putrefacto y un zombie hediondo). // En cambio si está a FALSE pondrá simplemente: En el este hay 2 zombies. // Por ahora tb devuelve los PSIS que eran invisibles... sorry :) sub ListaPsis(loc,verbose) declare(psis) declare(numpsis) declare(lista) declare(j) declare(obj) declare(obj2) declare(num) declare(desc) declare(texto) psis:=LOC[loc].PSIs() numpsis:=ArrayLen(psis) lista:="" while (numpsis>0) obj:=ArrayItem(psis,1) // Este es el patrón a buscar equivalencias if NOT(obj=PSIJugador) then // NOS SALTAMOS AL JUGADOR desc:="("+PSI[obj].DescCorta // esto se usa para añadir la descripción corta cuando hay varios y en verbose j:=2 // pues el patrón siempre será el elemento j=1, por tanto buscamos a partir de 2 num:=1 while (j<=numpsis) // bucle que busca ocurrencias respecto del nombre del patrón. obj2:=ArrayItem(psis,j) if NOT(obj2=PSIJugador) then // que no compare con el jugador. if PSI[obj2].nombre=PSI[obj].nombre then // si coincide con el patrón if (obj2="ZOMBIE HEMBRA")&NOT(muchacha) then // caso concreto de zombie hembra declare(NOP) // NO HACEMOS NADA PUES EL MENSAJE DE LA MUCHACHA LLAMANDO ESTÁ MÁS ABAJO else // este es el caso normal y corriente. num:=num+1 // esto suma la ocurrencia. desc:=desc+", "+PSI[obj2].DescCorta // almacena su descripción para el modo VERBOSE psis:=ArrayRemove(psis,j) // elimino la ocurrencia j:=j-1 // pa no joder la secuencia al borrar uno. endif endif endif numpsis:=ArrayLen(psis) // hay que actualizar la longitud, pues quizás se haya borrado algo. j:=j+1 loop if num=1 then // no ha encontrado ni una ocurrencia, por tanto sólo hay uno con ese nombre. if verbose then texto:=PSI[obj].DescCorta else if (obj="ZOMBIE HEMBRA")&NOT(muchacha) then // caso concreto pa la zombie hembra cuando parece que es una muchacha texto:="una muchacha que parece... ¡Parece que te llama con la mano!" else texto:="un "+LCase(PSI[obj].nombre) endif endif else // ha encontrado varios con mismo nombre if num=2 then texto:="un par de "+LCase(PSI[obj].nombre)+"s" else texto:=num+" "+LCase(PSI[obj].nombre)+"s" endif if verbose then // le añadimos las descripciones cortas concretas de cada uno. texto:=texto+" "+desc+")" // cerramos el paréntesis endif endif lista:=ArrayInsert(lista,ArrayLen(lista)+1,texto) // insertamos la cadena de texto endif // si obj no era el jugador psis:=ArrayRemove(psis,1) // borro el patrón. numpsis:=ArrayLen(psis) // ha habido muchos cambios... loop return lista // MueveMarabunta(), mueve la marabunta sub MueveMarabunta() turnomarabunta:=turnomarabunta-1 if turnomarabunta=0 then turnomarabunta:=3 Select movmarabunta Case 0 LOC["GENERADOR"].Marabunta:=TRUE Case 1 LOC["CALLE1"].Marabunta:=TRUE LOC["CALLE2"].Marabunta:=TRUE LOC["CALLEJON"].Marabunta:=TRUE if (PSI[PSIJugador].Localidad="EXPLANADA1")|(PSI[PSIJugador].Localidad="EXPLANADA2")|(PSI[PSIJugador].Localidad="EXPLANADA3")|(PSI[PSIJugador].Localidad="EXPLANADA4")|(PSI[PSIJugador].Localidad="EXPLANADA5")|(PSI[PSIJugador].Localidad="EXPLANADA6")|(PSI[PSIJugador].Localidad="18JULIO1") then print("La marabunta de zombies asoman por la calle al lado del Hospital de Santiago y por el callejón, al norte; y por la ") print("calle Nueva al este, inundando poco a poco la explanada con su horrenda presencia."+CR) endif Case 2 LOC["EXPLANADA1"].Marabunta:=TRUE LOC["EXPLANADA3"].Marabunta:=TRUE LOC["EXPLANADA6"].Marabunta:=TRUE if (PSI[PSIJugador].Localidad="EXPLANADA2")|(PSI[PSIJugador].Localidad="EXPLANADA4")|(PSI[PSIJugador].Localidad="EXPLANADA5")|(PSI[PSIJugador].Localidad="18JULIO1") then print("La multitud de zombies invaden con su blasfema presencia media explanada, sólo la mitad está libre de ellos... ") print("por poco tiempo."+CR) endif Case 3 LOC["EXPLANADA2"].Marabunta:=TRUE LOC["EXPLANADA5"].Marabunta:=TRUE if (PSI[PSIJugador].Localidad="EXPLANADA4")|(PSI[PSIJugador].Localidad="18JULIO1")|(PSI[PSIJugador].Localidad="18JULIO2")|(PSI[PSIJugador].Localidad="18JULIO3") then print("Los zombies avanzan, y desde aqui ves como la marea de espectros ocupa la explanada entera, salvo el principio de la cuesta."+CR) endif Case 4 LOC["EXPLANADA4"].Marabunta:=TRUE if (PSI[PSIJugador].Localidad="18JULIO2")|(PSI[PSIJugador].Localidad="18JULIO3") then print("Los marabunta de zombies empiezan a bajar, en tropel, por lo alto de la cuesta, en pos tuya."+CR) endif Case 5 LOC["18JULIO1"].Marabunta:=TRUE if (PSI[PSIJugador].Localidad="18JULIO2")|(PSI[PSIJugador].Localidad="18JULIO3") then print("La multitud de zombies avanzan calle abajo hacia ti. Están apunto de llegar a la zona de niebla, y tu te hayas entre la espada y la pared..."+CR) endif Case * if movmarabunta>=6 then LOC["18JULIO2"].Marabunta:=TRUE if (PSI[PSIJugador].Localidad="18JULIO3") then print("Al llegar la marabunta a la orilla de la niebla, se detiene. Parecen temerla."+CR) endif endif EndSelect movmarabunta:=movmarabunta+1 endif return // NoMueve(dir): // No pudo mover. Aqui pones tus razones. // Devuelve ret que si es TRUE ejecutará las excusas por defecto (no puedes ir por ahí) // Si devuelves FALSE es que has usado tú una de estas excusas. Sub NoMueve(dir) // WARNING: Si alguna localidad tiene conexión hacia si misma, con lo ke se contempla // en la descripción de las salidas; si quieres poner una razón para la que no vaya // por ella, fijate en la habitación de 18JULIO4, deberás poner ese texto en // USR_MueveJugador, y no aqui, ya que este sitio solo se ejecuta cuando falló el intento de // movimiento, y este no es el caso de las conexiones a si mismas, ya que son // un movimiento seguro (a menos que esté la puerta cerrada). declare(ret) declare(loc) ret:=TRUE loc:=PSI[PSIJugador].Localidad if (loc="TECHO") then Select dir Case "OESTE" print("Comienzas a caer lentamente hacia el oeste, de cabeza. Quizás ") print("querrías atravesar la ventana, pero tu 'forma astral' no te ") print("hace caso, y tu cabeza inunda la pared. Al instante una ") print("sensación terrible te asalta: estas invadiendo el espacio ") print("de la pared. Tu espacio vital se funde con ella y te produce un ") print("vértigo terrible. Te entra pánico y deseas volver, volver y..." + CR) USR_Fin(2) ret:=FALSE // el ESTE esta hecho en USR_MueveJugador, ya que es un salida hecha y derecha. Case "SUBIR" print("Por instinto giras y te encaras hacia el techo mientras avanzas ") print("hacia él. Tu nariz inicia la fusión, los antebrazos, pero... ") print("Tu espacio vital se funde con el hormigón, las vigas, el ladrillo... ") print("La sensación de vértigo y hormigeo es demasiado fuerte y... " + CR) USR_Fin(2) ret:=FALSE Case "BAJAR" print("Al empezar a bajar, tu cuerpo te reclama y con la misma sensación ") print("que cuando saliste de tu cuerpo, vuelves a entrar:" + CR) USR_Fin(2) ret:=FALSE Case * // aqui están contemplados el norte y el sur print("Empiezas a avanzar hacia la pared, pero al empezar a fundirte con ella, ") print("la sensación que te produce es demasiado fuerte, aguantas y aguantas, ") print("parece que vas a llegar AOL (Al Otro Lado), pero..."+CR) USR_Fin(2) EndSelect return ret EndIf return ret // conexiones. Devuelve imprime las conexiones de cualquier localidad. Sub Salidas(loc) declare(conexiones) declare(numconexiones) declare(lista) declare(i) declare(c) declare(lista) conexiones:=LOC[loc].Conexiones() numconexiones:=ArrayLen(conexiones)/2 // ya que devuleve pares (loc,verbo) If numconexiones>0 Then Print("\[N]Salidas: \[N]") lista:="" For i:=1 To numconexiones c:=LCase(ArrayItem(conexiones,(i*2)-1)) // recorre los elementos impares lista:=ArrayInsert(lista,ArrayLen(lista)+1,c) // inserta elementos Next Print(ArrayFormat(lista,", "," y ",".","") + CR) EndIf Return // TypeOf2(obj): // Esta rutina suple la carencia de la original TypeOf(obj), que cuando se introduce // en obj un nombre de objeto sin su adjetivo, y este lo tiene, TypeOf lo toma como // si este no existiera (tipo 0). // Esta nueva rutina, devuleve el tipo del primer objeto que encuentre con ese // nombre, aunque falte el adjetivo. // Se da por supuesto que a obj llega una palabra contenida en el vocabulario, pues // viene del análisis hecho por PARSE. sub TypeOf2(obj) declare(ret) declare(lista) declare(i) declare(nombrecompleto) declare(eureka) ret:=0 if obj<>"" then ret:=TypeOf(obj) if ret=0 then // puede ser que no se de ningún tipo o que sea por la carencia. lista:=Search(obj,"",9) // busca entre todos los objetos if ArrayLen(lista)>0 then ret:=2 // hemos encontrado un objeto else // ahora buscamos entre todos los PSIS, pues Search no lo permite. i:=0 eureka:=FALSE while NOT(eureka)&(i<=NumPsi) nombrecompleto:=PSI[i].Nombre +" "+ PSI[i].Adjetivo if In(1,nombrecompleto,obj)>0 then eureka:=TRUE ret:=3 // hemos encontrado un PSI que coincide endif i:=i+1 loop endif endif endif return ret // SUCESOS es una subrutina que engloba a todo lo que ha de suceder fuera de // las acciones del jugador. Aqui irá la inteligencia de Psis, sus movimientos, // posible paso del tiempo real de juego, eventos, etc etc // incluso aqui es el mejor sitio para actualizar la variable turnos, ya que quizás a // alguien le convenga no incrementar siempre el turno. Sub Sucesos() declare(array) turnos:=turnos + 1 if PSI[PSIJugador].estado<>"astral" then // todas las cosas de los zombies sólo pasan si el jugador no es ASTRAL. PSIs_IA() // mueve a todos lo psis... if PSI[PSIJugador].estado="devorado" then PSI[PSIJugador].estado:="normal" array:=PSI[PSIJugador].atacante if ArrayLen(array)=1 then print("Con esfuerzo te quitas de encima "+PSI[ArrayItem(array,1)].DescCorta+", el cual queda aturdido por unos instantes."+CR) else print("El dolor intensifica la adrenalina y consigues zafarte del abrazo mortal de estos espectros."+CR) endif endif PSI[PSIJugador].fuerza:=PSI[PSIJugador].fuerza + 5 if PSI[PSIJugador].fuerza>100 then PSI[PSIJugador].fuerza:=100 endif if PSI[PSIJugador].fuerza<0 then PSI[PSIJugador].fuerza:=0 endif EstadoJugador(FALSE) // imprime informes de salud y cansancio if (turnos>=horasegundaoleada)&NOT(segundaoleada) then segundaoleada:=TRUE Generar(6) Generar(7) endif if (turnos>=horamarabunta)&NOT(marabunta) then marabunta:=TRUE // Se activa la marabunta... print("Un murmullo incesante crece en el aire... es el sonido de cientos de almas en pena y del arrastrar de pies ") print("de la nación zombie. El hedor llena todo el aire. ") if (PSI[PSIJugador].Localidad="EXPLANADA1")|(PSI[PSIJugador].Localidad="EXPLANADA2")|(PSI[PSIJugador].Localidad="EXPLANADA3")|(PSI[PSIJugador].Localidad="EXPLANADA4")|(PSI[PSIJugador].Localidad="EXPLANADA5")|(PSI[PSIJugador].Localidad="EXPLANADA6")|(PSI[PSIJugador].Localidad="18JULIO1") then print("Desde aqui puedes ver como todos los zombies vienen ") print("de las salidas de la explanada al norte y al este.") endif print(CR) endif if marabunta then MueveMarabunta() if LOC[PSI[PSIJugador].Localidad].Marabunta=TRUE then Print("¡¡¡Los zombies llegan en marabunta hasta aqui!!!"+CR) USR_Fin(0) endif endif endif // si estaba el jugador en estado 'normal' return Sub ProcesaCond(comando) // este proceso te permite que los comandos introducidos por el jugador se ejecuten o // no (según las CONDICIONES que tú impongas). Para controlar posibles // situaciones criticas en contra del jugador. // Si devuelve TRUE, los comandos se ejecutan. // Lo suyo es introducir código de deteccion de condicion negativa y hacer res:=FALSE. // tambien se puede anular una acción según el ESTADO del jugador // (imagina que le han cortado los brazos), entonces se chequea una // variable de estado del jugador y se comprueba cuales son las // acciones prohibidas. Si "comando" a ejecutar esta entre ellas // pues se impide su ejecución. (por ejemplo coger con los brazos cortados). declare(ret) declare(frase) ret:=TRUE Select PSI[PSIJugador].Localidad Case "CUARTO" print("Vale... pero... \[C]¡¡¡Una sensación extraña te invade!!!. Notas algo que ") print("quiere salir de tu cuerpo. Un éxtasis que te corta la respiración." + CR) print("Tus pies se desculegan de tus pies y se elevan hacia arriba. Poco a poco ") print("tu cuerpo se va descolgando de tu cuerpo, quedando sujeto sólo por un último ") print("pelo de tu cabeza que al final acaba cediendo." + CR) print("Te elevas hacia el techo con un salto mortal hacia atrás. La ventana pasa ") print("ante tu aturdida vista, desde la posición sobre tu cabeza, en dos segundos, ") print("ahora la ves bajo tus pies: un paso adelante y te caerás por ella." + CR) print("Notas el vértigo en la mente (¿y el estómago?). Quedas flotando cerca del ") print("techo de tu habitación, en una vertiginosa ingravidez.\[C]" + CR) PSI[PSIJugador].Localidad:="TECHO" PSI[PSIJugador].estado:="astral" // este es el cambio de estado del jugador PSI[PSIJugador].DescCorta:="Sigues teniendo, extrañamente, el mismo aspecto de siempre, pero eres translúcido. Definitivamente esto debe ser una proyección mental de la imagen que tienes de ti mismo." ret:=FALSE Case * if (cansancio=4)&(PSI[PSIJugador].estado<>"astral") then // el jugador no podrá hacer nada if (INARRAY(prohibidos,ParseVerbo)<>0) then print("¡Imposible!. Estás completamente agotado, física y mentalmente. Arrodillado respiras profundamente para poder recobrar el aliento."+CR) PSI[PSIJugador].fuerza:=PSI[PSIJugador].fuerza+5 ret:=FALSE endif endif if (PSI[PSIJugador].estado="astral") then frase:=Parse(comando) // Aqui se usa el array prohibidos, que contiene los verbos que no se // podrán realizar cuando el jugador está en forma ASTRAL. Este array // está asignado en la zona de delcaraciones, pues es extenso y no tiene // setindo reasignarlo una y otra vez, cada vez que el juego entre en // en esta zona. if (INARRAY(prohibidos,ParseVerbo)<>0) then print("¡¡¡Imposible!!!, tu naturaleza astral te lo impide." + CR) ret:=FALSE endif endif EndSelect return ret Sub HayLuz(loc) // este procedimiento devuelve TRUE cuando hay luz en la localidad que se le pasa // como parámetro. declare(i) declare(i2) declare(hayluz) declare(objetos) declare(psis) // comprobamos si la localidad está a oscuras (no está iluminada y no es exterior) hayluz:=FALSE // por defecto no habrá luz If (LOC[loc].Iluminada) | (LOC[loc].Exterior) Then hayluz:=TRUE endif // en caso de que esté a oscuras comprobamos si hay una fuente de luz encendida, // bien en la localidad o bien la lleva un PSI encima // En objetos iremos metiendo los que tengan luz // esto los busca en la localidad y en las posesiones del jugador (opcion 0) objetos:=Search("*","Luz=1,Encendido=1",0) if ArrayLen(objetos)>0 then hayluz:=TRUE endif // Ahora busca entre los objetos de los psis psis:=LOC[loc].PSIs() // PROBARÉ teniendo en cuenta todos los Psis ke haya en la habitación i:=1 While (i<=ArrayLen(psis)) & NOT(hayluz) objetos:="" // inicializo por si las moscas objetos:=PSI[ArrayItem(psis,i)].Objetos() i2:=1 While (i2<=ArrayLen(objetos)) & NOT(hayluz) if OBJ[ArrayItem(objetos,i2)].Encendido then hayluz:=TRUE EndIf i2:=i2+1 loop i:=i+1 loop // Por último se podría hacer ke buske un objeto luminoso en los contenedores // Pero de eso paso. return hayluz