! ===================================================================== ! INFSP (Spanish Inform Library) ! ===================================================================== ! Author: INFSP Task Team ! Version: 0.9 ! Released: 21- Enero - 2009 ! Serial Number: 901.21 ! Note: For use with Inform 6. (Tested with Inform compiler ! version 6.31 and Inform library 6/11). ! Description: "An Inform library to write Interactive Fiction in ! Spanish. Language Spanish File." !================================================================ ! Spanish.h ! INFSP 0.9 libreria española para inform, basada en informATE de Zak ! .: by Sarganar :. ! ! Definición de todo lo relacionado con el idioma Español (artículos, ! nombres, pre-parsing, mensajes estandares, etc.) ! ! InformATE es (c) de Zak ! Re-edicion INFSP by Sarganar. Nuevas mejoras by colaboradores varios. ! caad.es/informate/infsp/ ! ---------------------------------------------------------------------------- System_file; Message "^Incluyendo Spanish: Mensajes y rutinas de idioma [INFSP 0.9]"; #Ifndef VN_1630; Message fatalerror "*** INFSP needs Inform v6.30 or later to work ***"; #Endif; ! VN_ ! [INFSP] Replacemnet Rutines. See INFSPR.H ----------------------------------------------------------- Replace DictionaryLookup; Replace PrefaceByArticle; Replace Identical; Replace TryGivenObject; Replace Indefart; Replace BestGuess; Replace NounDomain; ! --------------------------------------------------------------------------- ! Parte I. Asuntos preliminares ! --------------------------------------------------------------------------- Constant LanguageVersion = "Librería Española INFSP 0.9 [901.21], basada en InformATE!"; ! Definición de caractéres "baratos". Esto permite que estas letras ! ocupen menos bits en la máquina Z. No funciona si se intenta la ! compilación por módulos (viejo método) #ifdef TARGET_ZCODE; Zcharacter 'á'; ! a con acento Zcharacter 'é'; ! e con acento Zcharacter 'í'; ! i con acento Zcharacter 'ó'; ! o con acento Zcharacter 'ú'; ! u con acento Zcharacter 'ñ'; ! n con virguilla Zcharacter 'Ñ'; ! N con virguilla Zcharacter 'ü'; ! u con dieresis Zcharacter '¿'; ! abrir interrogación Zcharacter '¡'; ! abrir exclamación #endif; !---------------------------------------------- ! CONSTANTES Y CLASES ESPECIFICAS DE INFORMATE !---------------------------------------------- !Constant G_MASCULINO = 0; !Constant G_FEMENINO = 1; !Constant G_PLURAL = 3; Constant G_MASCULINO = 1; ! infsp new approach: para hacerlo bicompatible: I6/I7 Constant G_FEMENINO = 2; Constant G_PLURAL = 2; Class VerboIrregular; !------------------------------------ ! Globales específicas de InformatE! !------------------------------------ global PreguntaCualExactamente = 0; ! Esta variable se pone a 1 cuando se le pregunta al jugador ¿Cuál ! exactamente...? esto indica que puede ser necesario re-traducir la ! respuesta que el jugador dé, ya que puede que simplemente el jugador ! cambie de idea y en lugar de responder a nuestra pregunta introduzca ! un comando completamente nuevo. global PreguntaSiNo = 0; ! Esta variable debe ponerse a 1 manualmente si queremos que el verbo ! 'no' sea accesible como respuesta (y no como punto cardinal). La ! variable sólo afecta a la siguiente respuesta del jugador y vuelve a ! hacerse cero automáticamente. Global bandera_todo_vale; ! ¿y esta para qué sirve? Global quitacentos = 1; Array texto_impreso --> 52; Global dialecto_sudamericano = 0; !--------------------------------------------------------------------------- ! Atributos y propiedades específicas de InformatE!, tambien usados en INFSP !--------------------------------------------------------------------------- Property additive adjectives; Property gender 0; Property imperativo alias name; Property irrelevante alias name; Property name_m alias name; Property additive name_f; Property additive name_fp; Property additive name_mp; #ifdef ADMITIR_COMANDO_SALIDAS; Property salidas; #endif; Attribute nombreusado; ! usado internamente cuando se matchea el objeto por el nombre usado !================================================================ ! Los puntos cardinales !================================================================ Class CompassDirection with number 0, articles "El" "el" "", description [; if (location provides compass_look && location.compass_look(self)) rtrue; if (self.compass_look()) rtrue; L__M(##Look, 7, self); ], compass_look false, has scenery; Object Compass "brújula" has concealed female ; #Ifndef WITHOUT_DIRECTIONS; CompassDirection -> n_obj "norte" with name 'n//' 'norte', door_dir n_to; CompassDirection -> s_obj "sur" with name 's//' 'sur', door_dir s_to; CompassDirection -> e_obj "este" with name 'e//' 'este', door_dir e_to; CompassDirection -> w_obj "oeste" with name 'w//' 'o//' 'oeste', door_dir w_to; CompassDirection -> ne_obj "nordeste" with name 'ne' 'nordeste' 'noreste', door_dir ne_to; CompassDirection -> nw_obj "noroeste" with name 'no' 'nw' 'noroeste', door_dir nw_to; CompassDirection -> se_obj "sudeste" with name 'se' 'sureste' 'sudeste', door_dir se_to; CompassDirection -> sw_obj "sudoeste" with name 'so' 'sw' 'suroeste' 'sudoeste', door_dir sw_to; CompassDirection -> u_obj "arriba", with name 'u//' 'arriba' 'ar' 'r//' 'sube' 'techo' 'cielo', door_dir u_to, has proper; CompassDirection -> d_obj "abajo" with name 'd//' 'abajo' 'ab' 'b//' 'baja' 'piso' 'suelo', door_dir d_to, has proper; #endif; ! WITHOUT_DIRECTIONS CompassDirection -> in_obj "interior" with door_dir in_to, name 'en' 'dentro' 'adentro'; CompassDirection -> out_obj "exterior" with door_dir out_to, name 'fuera' 'afuera'; ! --------------------------------------------------------------------------- ! Parte II. Vocabulario ! --------------------------------------------------------------------------- Constant AGAIN1__WD = 'repetir'; Constant AGAIN2__WD = 're'; Constant AGAIN3__WD = 'g//'; Constant OOPS1__WD = 'oops'; Constant OOPS2__WD = 'epa'; Constant OOPS3__WD = 'eepa'; Constant UNDO1__WD = 'undo'; Constant UNDO2__WD = 'deshacer'; Constant UNDO3__WD = 'anular'; Constant ALL1__WD = 'todos'; Constant ALL2__WD = 'todas'; Constant ALL3__WD = 'todo'; Constant ALL4__WD = 'ambos'; Constant ALL5__WD = 'ambas'; Constant AND1__WD = 'y//'; Constant AND2__WD = 'y//'; Constant AND3__WD = 'e//'; Constant BUT1__WD = 'excepto'; Constant BUT2__WD = 'menos'; Constant BUT3__WD = 'salvo'; Constant ME1__WD = '-me'; Constant ME2__WD = '-te'; Constant ME3__WD = '-se'; Constant OF1__WD = '.de'; ! no usados nunca, pues provocan Constant OF2__WD = '.de'; ! interferencia con la preposición "de" Constant OF3__WD = '.de'; ! usada por algunos verbos, como en Constant OF4__WD = '.de'; ! "saca objeto de la caja" Constant OTHER1__WD = 'otro'; Constant OTHER2__WD = 'otra'; Constant OTHER3__WD = 'otro'; Constant THEN1__WD = 'ydespues'; Constant DESPUES11_WD = 'despues'; Constant THEN2__WD = 'yluego'; Constant DESPUES21_WD = 'luego'; Constant THEN3__WD = 'yentonces'; Constant DESPUES31_WD = 'entonces'; Constant NO1__WD = 'n//'; Constant NO2__WD = 'no'; Constant NO3__WD = 'no'; Constant YES1__WD = 's//'; Constant YES2__WD = 'si'; Constant YES3__WD = 'sí'; Constant AMUSING__WD = 'curiosidades'; Constant FULLSCORE1__WD = 'puntuacion'; Constant FULLSCORE2__WD = 'punt'; Constant QUIT1__WD = 'q//'; Constant QUIT2__WD = 'terminar'; Constant RESTART__WD = 'reiniciar'; Constant RESTORE__WD = 'recuperar'; Array LanguagePronouns table ! palabra GNAs que pueden conectado ! seguirle: a: ! a i ! s p s p ! mfnmfnmfnmfn '-lo' $$101000100001 NULL '-los' $$000101000101 NULL '-la' $$010000010000 NULL '-las' $$000010000010 NULL '-le' $$110000110000 NULL '-les' $$000110000110 NULL 'él' $$100000100000 NULL 'ella' $$010000010000 NULL 'ellos' $$000100000100 NULL 'ellas' $$000010000010 NULL; Array LanguageDescriptors table !palabra GNAs que pueden tipo de conectado ! seguirles: descriptor: con: ! a i ! s p s p ! mfnmfnmfnmfn 'mi' $$110110110110 POSSESS_PK 0 'este' $$100000100000 POSSESS_PK 0 'estos' $$000100000100 POSSESS_PK 0 'esta' $$010000010000 POSSESS_PK 0 'estas' $$000010000010 POSSESS_PK 0 'ese' $$100000100000 POSSESS_PK 1 'esa' $$010000010000 POSSESS_PK 1 'esos' $$000100000100 POSSESS_PK 1 'esas' $$000010000010 POSSESS_PK 1 'su' $$110000110000 POSSESS_PK '-le' 'sus' $$000110000110 POSSESS_PK '-le' 'el' $$100000100000 DEFART_PK NULL 'la' $$010000010000 DEFART_PK NULL 'los' $$000100000100 DEFART_PK NULL 'las' $$000010000010 DEFART_PK NULL 'un' $$100000100000 INDEFART_PK NULL 'una' $$010000010000 INDEFART_PK NULL 'unos' $$000100000100 INDEFART_PK NULL 'unas' $$000010000010 INDEFART_PK NULL 'algún' $$100000100000 INDEFART_PK NULL 'algunos' $$000100000100 INDEFART_PK NULL 'algunas' $$000010000010 INDEFART_PK NULL 'encendido' $$100000100000 light NULL 'encendida' $$010000010000 light NULL 'encendidos' $$000100000100 light NULL 'encendidas' $$000010000010 light NULL 'apagado' $$100000100000 (-light) NULL 'apagada' $$010000010000 (-light) NULL 'apagados' $$000100000100 (-light) NULL 'apagadas' $$000010000010 (-light) NULL; Array LanguageNumbers table 'un' 1 'uno' 1 'una' 1 'dos' 2 'tres' 3 'cuatro' 4 'cinco' 5 'seis' 6 'siete' 7 'ocho' 8 'nueve' 9 'diez' 10 'once' 11 'doce' 12 'trece' 13 'catorce' 14 'quince' 15 'dieciséis' 16 'diecisiete' 17 'dieciocho' 18 'diecinueve' 19 'veinte' 20; ! --------------------------------------------------------------------------- ! Parte III. Traducción ! --------------------------------------------------------------------------- !------------------------------------ ! Funciones de ayuda a la depuración !------------------------------------ [ ImprimeBuffer b desde l i; for (i=desde:ii; ]; [ ImprimeTodoElBuffer b; #ifdef TARGET_ZCODE; ImprimeBuffer(b, 2, b->1); #ifnot; !TARGET_GLULX ImprimeBuffer(b, WORDSIZE, b-->0); #endif; ]; #ifdef TARGET_GLULX; ! TARGET_GLULX [ PasarAMinuscula buffer ! [INFSP] Necesario en EspanolAInformes (en modo Glulx), para q el buffer i; ! sea reconocido (al usar infinitivo en mayuscula (EXAMINAR) o verbos pronominales (EXAMINALA) for (i=WORDSIZE:i<(WORDSIZE+(buffer-->0)):i++) buffer->i = LowerCase (buffer->i); return buffer; ]; #endif; !TARGET_ !---------------------------------------------------------------- ! [010515] Rutina nueva, que recibe una palabra de diccionario y un ! lugar donde buscar, y retorna "true" si alguno de los objetos de ese ! lugar tiene esa palabra en su campo nombre, name_f... ! ! Es usada por la rutina ArreglarLosY, pues se mira si la palabra que ! viene detrás de la Y es un nombre, y si lo es, si es aplicable a algún ! objeto cercano. Observar que fallará en los objetos que proporcionen ! su propio parse_name. !---------------------------------------------------------------- [ EncajeSimplon w donde i; objectloop(i in donde) { if (WordInProperty(w, i, name)) rtrue; if (WordInProperty(w, i, name_f)) rtrue; if (WordInProperty(w, i, name_mp)) rtrue; if (WordInProperty(w, i, name_fp)) rtrue; if (WordInProperty(w, i, adjectives)) rtrue; if (children(i) && EncajeSimplon(w, i)) rtrue; } rfalse; ]; ! ---------------------------------------------------------------------------- ! Las siguientes pueden ser útiles para los programadores de los ! ficheros de definición de lenguaje ! ---------------------------------------------------------------------------- ! InsertarLetraBuffer ya es soportada por la funcion de fábrica LTI_Insert [ BorrarBuffer b p i; ! infsp TODO : esta funcion no se usa, la borramos? ! Rellena con espacios el buffer for (i=2:ii=' '; Tokenise__(b, p); ]; !---------------------------------------------------------------- ! QuitarAcentos ! ! La siguiente función prueba a quitar los acentos de las palabras que ! no hayan podido ser interpretadas. De este modo, el jugador puede usar ! o no los acentos. Para ello el juego debe definir las palabras sin acentos ! por ejemplo: ! object sillon "sillón confortable" ! with name 'sillon' 'confortable' ! ! Si el jugador pone: "mira sillon", la palabra encaja directamente y es ! comprendida. Si pone "mira sillón", no es comprendida, de modo que se ! le quita el acento y se reintenta el parsing. ! ! Este caso no es especialmente importante, pues el programador ! siempre puede definir 'sillon' y 'sillón', ambos como nombres para ! el objeto. Pero el asunto es más importante para el caso de los ! verbos, ya que si el jugador teclea "cógelo" este es separado en ! "cóge" y "-lo" y el verbo "cóge" (con acento) no sería ! comprendido. ! ! La llamada a esta función puede desactivarse con el comando de ! debugging "acentos sí" de modo que los acentos que teclee el jugador ! no serán eliminados (con propósitos de depuración) [ QuitarAcentos buf pars x i word at len; if (parser_trace >= 7) ! imprimir el buffer recibido { print "^[ QuitarAcentos: "; print "Buffer recibido: |"; ImprimeTodoElBuffer(buf); print "|^"; } tokenise__(buf, pars); for (x=1:x<=tokenCount(pars):x++) ! para cada token { word = tokenDict (pars,x); !dictionary value of token 1,2,3... at = tokenPos (pars,x); ! position in buffer of token 1,2,3... len = WordLength (x);! length in chars of token 1,2,3... if (word==0) ! no comprendida { if (parser_trace>=7) { print " QuitarAcentos:NO COMPRENDIDO: |"; ImprimeBuffer(buf, at, len); print "|^"; } for (i=at:ii) { 'á': buf->i='a'; 'é': buf->i='e'; 'ë': buf->i='e'; 'í': buf->i='i'; 'ó': buf->i='o'; 'ú': buf->i='u'; 'ü': buf->i='u'; 'ñ': buf->i='n'; ! '?': buf->i=' '; ! '¿': buf->i=' '; ! '!': buf->i=' '; ! '¡': buf->i=' ' ; } tokenise__(buf, pars); } } if (parser_trace>=7){ print " Buffer sin acentos: |"; ImprimeTodoElBuffer(buf); print "|^"; } ]; ! funciones de soporte para gestionar parse y buffer ! From InformFAQ - Roger Firth [ tokenDict pars w; ! dictionary value of token 1,2,3... #Ifdef TARGET_ZCODE; return pars-->(2*w - 1); #Ifnot; ! TARGET_GLULX return pars-->(3*w - 2); #Endif; ! TARGET_ ]; [ tokenLen pars w; ! length in chars of token 1,2,3... #Ifdef TARGET_ZCODE; return pars->(4*w); #Ifnot; ! TARGET_GLULX return pars-->(3*w - 1); #Endif; ! TARGET_ ]; [ tokenPos pars w; ! position in buffer of token 1,2,3... #Ifdef TARGET_ZCODE; return pars->(4*w + 1); #Ifnot; ! TARGET_GLULX return pars-->(3*w); #Endif; ! TARGET_ ]; [ tokenCount pars; #Ifdef TARGET_ZCODE; return pars->1; #Ifnot; ! TARGET_GLULX return pars-->0; #Endif; ! TARGET_ ]; !----------------------------------------------------- ! LanguageToInformese ! ! Esta parte es interesante. Debe separar los sufijos pronominales ! como en "cogela" "mirale", claro que no basta con ver si las dos ! últimas letras del verbo son "la" "le", etc, pues el verbo podría ! terminar de forma "natural" en esas letras (como en "habla"). Así ! que hay que separar el sufijo sólo si el verbo no ha sido hallado en ! el diccionario. ! [ LanguageToInformese ; EspanolAInformes(buffer, parse); ]; ! La función que verdaderamente hace la traducción es la siguiente. Ha ! sido separada de LanguageToInformese porque es llamada también desde ! LanguageIsVerb, pero recibe un buffer diferente para procesar. [ EspanolAInformes buf pars x i word at len romper_en siguiente retokenise at2; ! print " EspanolAInformes called^"; ! infsp debug #ifdef TARGET_GLULX; ! TARGET_GLULX buf = PasarAMinuscula (buf); ![INFSP] Necesario para q no cazque al procesar infinitivos #endif; tokenise__( buf, pars); retokenise=0; if (parser_trace>=7) !imprimir el buf recibido { print "^[ EspanolAInformes: "; print "Buffer recibido: |"; ImprimeTodoElBuffer(buf); print "|^ "; } if (quitacentos) QuitarAcentos(buf, pars); for (x=1:x<=tokenCount(pars):x++) ! para cada token { word = tokenDict (pars,x); !dictionary value of token 1,2,3... at = tokenPos (pars,x); ! position in buffer of token 1,2,3... len = tokenLen (pars,x);! length in chars of token 1,2,3... if (parser_trace>=7){ print "Palabra ",x," : "; if (word==0) print ""; else print (address) word," ^"; print " ^"; } if (dialecto_sudamericano && (word == 'coge')) { ! Un poco bestia, pero funciona. En caso de dialecto sudamericano, ! cambiar un par de letras convierte "coge" en "jode" buf->(at) = 'j'; buf->(at + 2) = 'd'; retokenise = 1; if (dialecto_sudamericano == 1) ! [071030_git] { print "[Este juego utiliza por defecto el dialecto sudamericano, por lo que aquí COGER es entendido como una palabra malsonante. Por favor, utiliza TOMAR en su lugar, o bien elige el dialecto castellano con DIALECTO CASTELLANO.]^"; dialecto_sudamericano = 2; } } if (word=='del' or 'al') { buf->(at+len-1)=' '; ! convertir "del" "al" en "de" ! "a" respectivamente retokenise=1; } ! Si el jugador ha escrito "no", y previamente el programador ! había puesto a 1 el flag "PreguntaSiNo" (que indica que ! acaba de hacerse una pregunta que podría admitir NO como ! respuesta), en ese caso cambiamos "no" por "xo". La ! gramática define el verbo "xo" para generar la acción NO ! (negar), y así lo distinguimos de la acción "Ir noroeste" if ((word=='no')&&(PreguntaSiNo==1)) { buf->(at+len-1)='x'; PreguntaSiNo=0; retokenise=1; } ! "pegar" las expresiones "y luego" "y despues" "y entonces" ! para que queden "yluego" "ydespues" "yentonces" ! que es como las reconoce el parser if (word=='y//') { siguiente= tokenDict (pars,x+1); ! palabra siguiente if (siguiente==DESPUES11_WD or DESPUES21_WD or DESPUES31_WD) { at2 = tokenPos (pars,x+1); ! position in buffer of token 1,2,3... for (i=0:i(at2+i) = ' '; ! borrar palabra 'entonces' (pisándola con espacios) } buf->(at+len)='l'; ! agregar 'luego' inmediatamente despues de 'y', formando 'yluego' buf->(at+len+1)='u'; buf->(at+len+2)='e'; buf->(at+len+3)='g'; buf->(at+len+4)='o'; retokenise=1; if (parser_trace>=7) !imprimir el buf recibido { print "^[ YLUEGO: "; print "Buffer recibido: |"; ImprimeTodoElBuffer(buf); print "|^ "; } } } if (word==0) ! no comprendida { if (parser_trace>=7) { print "NO COMPRENDIDO: |"; ImprimeBuffer(buf, at, len); print "|^"; } if (len > 2) !sólo si tiene más de tres letras { romper_en=0; if ((buf->(at+len-1)=='s') && (buf->(at+len-2)=='a' or 'o' or 'e') && (buf->(at+len-3)=='l')) romper_en=3; if ((buf->(at+len-1)=='a' or 'o' or 'e') && (buf->(at+len-2)=='l')) romper_en=2; if ((buf->(at+len-1)=='e') && (buf->(at+len-2)=='m' or 't' or 's')) romper_en=2; ! [001108] Antes ponía == ¡seré burro! if (romper_en) { ! [990524] ! Antes de modificar el buffer, comprobemos si ! servirá para algo, es decir, si la palabra que ! queda una vez separado el sufijo existe en el ! diccionario y es un verbo i=DictionaryLookup(buf+at, len-romper_en); if (i) if ((i->#dict_par1)&1) { LTI_Insert(at+len-romper_en, '-', buf); LTI_Insert(at+len-romper_en, ' ', buf); tokenise__(buf,pars); } if (QuitandoRFinal(buf+at, len-romper_en)|| BuscarEntreVerbosIrregulares(buf+at, len-romper_en)) { LTI_Insert(at+len-romper_en, '-', buf); LTI_Insert(at+len-romper_en, ' ', buf); tokenise__(buf,pars); } } ! if (romper_en } ! if (len > 2 } ! if (word==0 } ! for (x=0: if (retokenise==1) ! [INFSP] Agregado if, como en la seccion Glulx tokenise__(buf, pars); ArreglarLosY(buf, pars); ! Como paso final, quitamos las palabras que aparezcan dos veces ! seguidas. Esto puede ocurrir si el jugador teclea un comando ! incompleto, como "MIRA HACIA", y el parser le pregunta "¿Hacia ! donde quieres mirar?" y el jugador responde "HACIA EL NORTE". En ! este caso se construiría la orden concatenada: "MIRA HACIA HACIA ! EL NORTE". if (PreguntaCualExactamente==1){ PreguntaCualExactamente=0; EliminarDuplicados(buf, pars); } if (parser_trace>=7){ print "Buffer traducido a informese: ^|"; ImprimeTodoElBuffer(buf); print "| (", pars->1," palabras) ^"; } ]; [ ArreglarLosY buf pars word at len x i retoke; for (x=1:x<=tokenCount(pars):x++) ! para cada token { word = tokenDict (pars,x); !dictionary value of token 1,2,3... if (word=='y//') { i = tokenDict (pars,x+1); ! palabra siguiente ! [010515] arreglado bug. at y len no apuntaban a la ! palabra siguiente, sino a la propia 'y', por lo que no ! eran reconocidos los verbos en infinitivo at = tokenPos (pars,x+1); ! position in buffer of token siguiente len = tokenLen (pars,x+1);! length in chars of token siguiente ! [010515] Añadido. Si la palabra es noun, se retorna ! (aunque pueda ser también un verbo) de este modo, en ! COGE VINO Y CAVA, si el juego tiene un objeto llamado ! "cava", la frase será parseada como tratando de coger ! dos objetos, llamados "vino" y "cava". Si el juego no ! define el sustantivo "cava", la frase será parseada como ! dos acciones en secuencia <> y <> if (i && (i->#dict_par1)&128) { if (EncajeSimplon(i, location)) continue; } if (i && ((i->#dict_par1)&1)||QuitandoRFinal(buf+at,len)|| BuscarEntreVerbosIrregulares(buf+at, len)) { at = tokenPos (pars,x); ! position in buffer of token siguiente buf->(at)='.'; retoke=true; } } } if (retoke) tokenise__(buf, pars); ]; [ EliminarDuplicados buf pars word at len x i siguiente retokenise; ! tokenise__(buf, pars); if (parser_trace>=8) !imprimir el buffer recibido { print "^[ EliminarDuplicados: "; print "Buffer recibido: |"; ImprimeTodoElBuffer(buf); print "| (", pars->1, " palabras)^"; } for (x=1:x<=tokenCount(pars):x++) ! para cada token { word = tokenDict (pars,x); !dictionary value of token 1,2,3... siguiente = tokenDict (pars,x+1); !dictionary value of token 1,2,3... at = tokenPos (pars,x); ! position in buffer of token 1,2,3... len = tokenLen (pars,x);! length in chars of token 1,2,3... if ((word==siguiente) && (word~=0)) { if (parser_trace>=8) print "Encontrados duplicados!:", (address) word, "=", (address) siguiente, ".^"; for (i=at:ii=' '; retokenise=1; } } if (retokenise) tokenise__(buf, pars); if (parser_trace>=8) !imprimir el buffer recibido { print "Buffer resultante: |"; ImprimeTodoElBuffer(buf); print "| (", pars->1, " palabras)^"; } ]; ! La siguiente función debe devolver si el verbo recibido es ! reconocido o no. Se recibe el buffer completo y "pos" indica qué ! palabra dentro del buffer "pars" es el supuesto verbo. ! Hay que devolver la dirección de diccionario del verbo en cuestión. ! ! Lo usamos para admitir infinitivos. El método es: ! Si la palabra corresponde a una palabra de diccionario, no hacemos ! nada (retornamos esa palabra, sin molestarnos en comprobar que sea ! un verbo. Ya lo hará el parser). ! ! Si la palabra no está en el diccionario, miramos si termina en ! 'r', y de ser así se la quitamos y re-tokenizamos. Si de este modo ! se obtiene una palabra en el diccionario, retornamos su valor (sin ! comprobar que sea un verbo, ya lo hará el parser). ! ! Si tampoco de este modo se reconoce, comparamos la palabra dada ! con todos los verbos irregulares conocidos. Si en uno de ellos ! encontramos coincidencia, retornamos el primer elemento de la ! propiedad "imperativo" del verbo en cuestión. ! ! En el caso de la desambiguacion, puede darse que el jugador responda ! con un verbo nuevo, pero con sufijo pronominal la/le/lo/me/te/se (ej. examinala) ! Por ello se hace una llamada a EspanolAInformes [ LanguageIsVerb buf pars pos i word at len; if (parser_trace>=7) !imprimir el buffer recibido { print "^[ LanguageIsVerb: "; print "Buffer recibido: |"; ImprimeTodoElBuffer(buf); print "|, pos=", pos, "^ "; } if (PreguntaCualExactamente) ! caso de desambiguación EspanolAInformes(buf, pars); ! revisar la existencia de sufijos pronominales la/le/lo/me/te/se word = tokenDict (pars,pos); !dictionary value of token 1,2,3... at = tokenPos (pars,pos); ! position in buffer of token 1,2,3... len = tokenLen (pars,pos);! length in chars of token 1,2,3... ! Si la palabra se reconoce, devolverla sin más if (word~=0 && word->#dict_par1 & 1 ~= 0) { if (parser_trace>=7) print " la palabra ~", (address) word, "~ está en el diccionario.^"; return (word); } ! Si no, probar a ver si se reconoce sin la 'r' final i=QuitandoRFinal(buf + at,len); ! Si no la ha reconocido, intentamos ver si es un verbo irregular if (i~=0) { if (parser_trace>=7) print "^ Verbo reconocido al quitarle la 'r' final.^"; } else { if (parser_trace>=7) print "^ Verbo no reconocido sin la 'r'. ^Probando irregulares..."; i=BuscarEntreVerbosIrregulares(buf + at,len); if (parser_trace>=7) { if (i==0) print "No reconocido como irregular.^"; else print " Reconocido como el verbo ", (address) i, "^"; } } if (parser_trace>=7) print " ^ -- end LanguageIsVerb ]^"; return i; ]; !#ifdef ADMITIR_INFINITIVOS; [ QuitandoRFinal texto longitud i; if (parser_trace>=9) { print "^[ QuitandoRFinal: buffer recibido |"; ImprimeBuffer(texto, 0, longitud); print "|^"; } if (texto->(longitud-1)~='r') { if (parser_trace>=9) print "No termina en 'r'^"; return 0; } i=DictionaryLookup(texto, longitud-1); ! if ((dialecto_sudamericano==1)&&(i=='coge')) return 'jode'; if (dialecto_sudamericano && (i == 'coge')) { if (dialecto_sudamericano == 1) ! [071030] git { print "[Este juego utiliza por defecto el dialecto sudamericano, por lo que aquí COGER es entendido como una palabra malsonante. Por favor, utiliza TOMAR en su lugar, o bien elige el dialecto castellano con DIALECTO CASTELLANO.]^"; dialecto_sudamericano = 2; } return 'jode'; } if ((i->#dict_par1)&1) return i; else { if (parser_trace>=9) print "Está en el diccionario, pero no es verbo.^"; return 0; } ]; [ BuscarEntreVerbosIrregulares texto longitud verbo i k; objectloop (verbo ofclass VerboIrregular) { if (parser_trace>=8) print "^[Bucando irregulares. Probando con ~", (name) verbo, "~.-->"; #ifdef TARGET_ZCODE; texto_impreso-->0 = 50; @output_stream 3 texto_impreso; print (name) verbo; @output_stream -3; k=texto_impreso-->0; #endif; #ifdef TARGET_GLULX; k=PrintAnyToArray(texto_impreso+WORDSIZE, 46, verbo); #endif; !TARGET_ !Si sus longitudes no coinciden no es necesario seguir comparando if (k~=longitud) jump NoCoincide; !Si sus longitudes coinciden, miramos letra a letra for (i=0:ii)~=(texto_impreso->(i+WORDSIZE))) jump NoCoincide; ! si una sola letra no coincide, ! Si ha pasado los test anteriores, hemos hallado una ! coincidencia if (parser_trace>=8) print "¡coincide!^"; return (verbo.&imperativo-->0); .NoCoincide; if (parser_trace>=8) print "no coincide^"; } return 0; ]; !#endif; !ADMITIR_INFINITIVOS ! --------------------------------------------------------------------------- ! Parte IV. Imprimir ! --------------------------------------------------------------------------- ! Definimos una función para imprimir el verbo coger. Esto hace más fácil ! la adaptación de los juegos a los dialectos sudamericanos, en los ! que debe usarse "tomar" en lugar de "coger" ! ! La variable global que elige el dialecto se fija en tiempo de ! ejecución con el meta-verbo "dialecto". También puede fijarse en ! Initialize para que su valor por defecto sea 1. ! [ coge sufijo; if (dialecto_sudamericano) print "toma"; else print "coge"; if (sufijo ~= 0) print (string) sufijo; ]; ! La siguiente es la versión con la primera letra mayúscula [ MCoge sufijo; if (dialecto_sudamericano) print "Toma"; else print "Coge"; if (sufijo ~= 0) print (string) sufijo; ]; ! Y finalmente una versión con todo mayúsculas [ MMCoge sufijo; if (dialecto_sudamericano) print "TOMA"; else print "COGE"; if (sufijo ~= 0) print (string) sufijo; ]; Constant LanguageAnimateGender = male; Constant LanguageInanimateGender = male; Constant LanguageContractionForms = 1; ! Para el español ! No se produce contracción del artículo. Sólo de las preposiciones ! como en "del" y "al", pero eso no está contemplado por el manual ! del traductor, por lo que es necesario otro tipo de truco [ LanguageContraction ; return 0; ]; Array LanguageArticles --> ! Forma de contracción 0: ! Cdef Def Indef "El " "el " "un " "La " "la " "una " "Los " "los " "unos " "Las " "las " "unas "; ! a i ! s p s p ! m f n m f n m f n m f n Array LanguageGNAsToArticles --> 0 1 0 2 3 2 0 1 0 2 3 2; [ LanguageDirection d; ! [INFSP] Se agregaron los articulos, para una correcta impresion. switch(d) ! Usado en PrintCommand y en Salidas. { n_to: print "al norte"; s_to: print "al sur"; e_to: print "al este"; w_to: print "al oeste"; ne_to: print "al nordeste"; nw_to: print "al noroeste"; se_to: print "al sudeste"; sw_to: print "al suroeste"; u_to: print "arriba"; d_to: print "abajo"; in_to: print "dentro"; out_to: print "fuera"; default: return RunTimeError(9,d); } ]; [ LanguageNumber n venti m; if (n==0) { print "cero"; rfalse; } if (n<0) { print "menos "; n=-n; } if (n>=1000) { if (n<2000) print "mil"; else { LanguageNumber(n/1000,1); print " mil";} n=n%1000; if (n~=0) print " "; } if (n>=100) { CientosEspanol(n/100); if (n%100~=0) print " "; n=n%100; } if (n==0) rfalse; if (n<10) { DigitoEspanol(n); rfalse; } if (n>=20) { m=n/10; if (n%10~=0) { if (m==2) print "veinti"; } else { if (m==2) print "veinte"; } if (m==3) print "treinta"; if (m==4) print "cuarenta"; if (m==5) print "cincuenta"; if (m==6) print "sesenta"; if (m==7) print "setenta"; if (m==8) print "ochenta"; if (m==9) print "noventa"; if (n%10==0) rfalse; if (m>2) print " y "; DigitoEspanol(n%10, (m==2)&&(venti==0)); rfalse; } if (n==10) { print "diez"; rfalse; } if (n==11) { print "once"; rfalse; } if (n==12) { print "doce"; rfalse; } if (n==13) { print "trece"; rfalse; } if (n==14) { print "catorce"; rfalse; } if (n==15) { print "quince"; rfalse; } if (n==16) { print "dieciséis"; rfalse; } if (n==17) { print "diecisiete"; rfalse; } if (n==18) { print "dieciocho"; rfalse; } print "diecinueve"; ]; [ DigitoEspanol n venti; if (n==1) { print "un"; rfalse; } if (n==2) { if (venti) {print "dós";} else {print "dos"; }; rfalse; } if (n==3) { if (venti) {print "trés";} else {print "tres"; }; rfalse; } if (n==4) { print "cuatro"; rfalse; } if (n==5) { print "cinco"; rfalse; } if (n==6) { if (venti) {print "séis";} else {print "seis"; }; rfalse; } if (n==7) { print "siete"; rfalse; } if (n==8) { print "ocho"; rfalse; } if (n==9) { print "nueve"; rfalse; } ]; [ CientosEspanol n; if (n==1) { print "ciento"; rfalse; } if (n==2) { print "dos";} if (n==3) { print "tres";} if (n==4) { print "cuatro";} if (n==5) { print "quinientos"; rfalse;} if (n==6) { print "seis";} if (n==7) { print "sete";} if (n==8) { print "ocho";} if (n==9) { print "nove";} print "cientos"; rfalse; ]; [ LanguageTimeOfDay hours mins i; i=hours%12; if (i<10) print " "; if (i==0) i=12; print i, ":", mins/10, mins%10; if ((hours/12) > 0) print " pm"; else print " am"; ]; [ LanguageVerb i aux; if (ImprimirIrregular(i)==0){ !print "^ LanguageVerb: Verbo no es irregular.^"; ! infsp debug ! Tatar de matchear con la brújula - 807.7 infsp objectloop (aux ofclass CompassDirection){ if (WordInProperty(i, aux, name)) { print "ir hacia algún lado"; ! !LanguageDirection (aux.door_dir); ! the direction name as adverb rtrue; ! no avanzar más en la rutina } } ! Un ultimo intento, con una rutina stub a proveer por el autor if (PrintVerb(i)==0){ print (address) i; print "r"; } } if (i=='mete') rtrue; #ifdef TARGET_ZCODE; ! Comprobemos si era un verbo reflexivo (-te) texto_impreso-->0 = 50; @output_stream 3 texto_impreso; print (address) i; @output_stream -3; aux=2; ! print "^ LanguageVerb: i : ",(address) i,"^"; ! infsp debug if (texto_impreso->(texto_impreso->1+1)=='e') if (texto_impreso->(texto_impreso->1) == 't' or 's' or 'm') { ! print "^ LanguageVerb:Verbo reflexivo."; ! infsp debug if (actor ~= player) print "se"; else print (string) PARTICULA_TE; ! "te" } #endif; #ifdef TARGET_GLULX; aux=PrintAnyToArray(texto_impreso, 50, i); if ((texto_impreso->(aux-1)=='e')&& (texto_impreso->(aux-2) == 't' or 's' or 'm')) { if (actor ~= player) print "se"; else print (string) PARTICULA_TE; } #endif; rtrue; ]; [ ImprimirIrregular v i; ! Imprime los verbos irregulares (es decir, aquellos en los que no basta ! añadir una "r" al imperativo). Por ejemplo, si el jugador teclea "friega" ! la respuesta por defecto sería "¿Qué quieres friegar?" ! Para evitar esto, el programador debe definir un objeto de la clase ! VerboIrregular, con nombre "fregar" y propiedad name = "friega" ! Esta rutina busca entre los verbos así definidos, en el campo name ! y si encuentra una coincidencia imprime el nombre del objeto para ! el cual se halló. ! Para mayor flexibilidad aún, se permite que el programador incluya ! una rutina en la propiedad nombre_corto del verbo, por si el nombre ! del verbo a imprimir es variable según el momento en que se llame. ! Si existe nombre_corto para el verbo en cuestión, se ejecuta dicha rutina ! de lo contrario se imprime el nombre de ese verbo sin más. ! Ver SpanishG.h para ejemplos de declaración de verbos irregulares. objectloop (i ofclass VerboIrregular) if (WordInProperty(v, i, imperativo)) { if (i.&short_name~=0) return(PrintOrRun(i, short_name, 1)); else { print (name) i; rtrue;}} rfalse; ]; ! ---------------------------------------------------------------------------- ! LanguageVerbIsDebugging is called by SearchScope. It should return true ! if word w is a debugging verb which needs all objects to be in scope. ! ---------------------------------------------------------------------------- #Ifdef DEBUG; [ LanguageVerbIsDebugging w; if (w == 'xroba' or 'xarbol' or 'xmueve' or 'irdonde' or 'scope' or 'xobjeto' or 'alcance' or 'xir') rtrue; rfalse; ]; #Endif; ! ---------------------------------------------------------------------------- ! LanguageVerbLikesAdverb is called by PrintCommand when printing an UPTO_PE ! error or an inference message. Words which are intransitive verbs, i.e., ! which require a direction name as an adverb ('walk west'), not a noun ! ('I only understood you as far as wanting to touch /the/ ground'), should ! cause the routine to return true. ! ---------------------------------------------------------------------------- [ LanguageVerbLikesAdverb w; if (w == 'vete' or 've' or 'camina' or 'anda' or 'corre' or 'vuelve' or 'ir') rtrue; rfalse; ]; ! ---------------------------------------------------------------------------- ! LanguageVerbMayBeName is called by NounDomain when dealing with the ! player's reply to a "Which do you mean, the short stick or the long ! stick?" prompt from the parser. If the reply is another verb (for example, ! LOOK) then then previous ambiguous command is discarded /unless/ ! it is one of these words which could be both a verb /and/ an ! adjective in a 'name' property. ! ---------------------------------------------------------------------------- [ LanguageVerbMayBeName w j first_word; j=j; first_word=first_word; if (w == 'long' or 'short' or 'normal' or 'brief' or 'full' or 'verbose' or 'saltar') rtrue; rfalse; ]; Constant NKEY__TX = "S = Siguiente"; Constant PKEY__TX = " P=Previo"; Constant QKEY1__TX = "Q=Volver al juego"; Constant QKEY2__TX = "Q = Menú anterior"; Constant RKEY__TX = "INTRO = leer este tema"; Constant NKEY1__KY = 'S'; Constant NKEY2__KY = 's'; Constant PKEY1__KY = 'P'; Constant PKEY2__KY = 'p'; Constant QKEY1__KY = 'Q'; Constant QKEY2__KY = 'q'; Constant SCORE__TX = "Punt.: "; Constant MOVES__TX = "Movim.: "; Constant TIME__TX = "Hora: "; Constant DARKNESS__TX = "Oscuridad"; ! En la revisión [020415] las constantes HAY*__TX se han trasladado al ! fichero Mensajes, pues dependen del tiempo, persona y número verbales. ! INFSP - Se volvieron a su lugar, pues no se usa Mensajes.h Constant THOSET__TX = "esas cosas"; Constant THAT__TX = "eso"; Constant OR__TX = " o "; Constant NOTHING__TX = "nada"; Constant AND__TX = " y "; Constant WHOM__TX = "que "; ! Al parecer, aquí sobraban los espacios Constant WHICH__TX = "que "; ! de antes de los 'que'. [020423] Constant COMMA__TX = ", "; ! Funciones para manejar concordancias de género y número en los ! mensajes de respuesta genéricos. ! ! o -> escribe la terminación -o -a -os -as según el género y número ! del objeto recibido, para hacer concordar los adjetivos. ! ! n -> escribe la terminación -"" -n según el número del objeto, para ! hacer concordar el verbo en plural. ! ! esta -> escribe "está" o "están" según el número del objeto. ! ! del -> escribe "del" "de la" "de los" "de las" según el género y ! número del objeto. En realidad, determina qué artículo habría de ir ! y si éste es "el" realiza la contracción "del". ! ! al -> como del, pero con "al" "a la" "a los" "a las". ! ! lo -> Escribe "lo" "la" "le" "los" "las" "les" (proname) según el ! género y número del objeto y según sea animate o no. ! [ o obj gna; gna=GetGNAOfObject(obj); switch(gna) { 0,6: print "o"; 1,7: print "a"; 3,9: print "os"; 4,10: print "as"; } ]; [ e obj gna; gna=GetGNAOfObject(obj); switch(gna) { 0,6: print "e"; 1,7: print "a"; 3,9: print "es"; 4,10: print "as"; } ]; [ n obj; if (obj == player) print "s"; else if (obj has pluralname) print "n"; ]; [ s obj; if (obj has pluralname) print "s"; ]; [ esta obj; print "está", (n) obj; ]; [ es obj; if (obj has pluralname) print "son"; else print "es"; ]; [ _Es obj; if (obj has pluralname) print "Son"; else print "Es"; ]; [ _s obj; if (obj has pluralname) print "es"; ]; [ el_ obj; if (obj hasnt proper) PrefaceByArticle(obj,1,-1); ]; [ un_ obj; if (obj hasnt proper) PrefaceByArticle(obj,2,-1); ]; [ el obj; print (the) obj; ]; [ _El obj; print (The) obj; ]; ![ un obj; ! if (un_(obj)) print " "; ! print (name) obj; !]; [ un obj; ! if (obj has proper) print "a "; ![infsp] ya se incluyó esta linea en el hackeo de Indefart. print (a) obj; ]; [ _Un obj; ! indefinido con la primera letra en mayuscula. -Eliuk Blau print (A) obj; ]; [ _nombre_ obj; print (name) obj; ]; [ numero obj; print (number) obj; ]; ! "al" y "del" plantean un bonito problema. La contracción debe ! producirse si el artículo es "el", pero esto no se sabe consultando ! el GNA, pues hay palabras como "aguila" que son femeninas y no ! obstante usan "el" como artículo. ! El truquillo consiste en llamar a (the) para averiguar qué artículo ! se imprimiría (pero capturando la salida de ese print y guardándola ! en una variable). Si el artículo en cuestión empieza por 'e', se ! produce la contracción. ! ! Para capturar la salida a una variable, es necesario descender al ! lenguaje ensamblador de la Z machine. Este truco lo aprendí del ! Designers manual (respuesta al ejercicio 96, página 249) ! !------------------------------------------------------------------------------ ! ELIUK BLAU: He re-implementado la rutina para permitir que la primera letra ! se imprima en mayuscula si se activa el argumento 'flag' durante la llamada. [ del_ obj flag; ! ELIUK: 'flag' es usado solo por rutina de impresion (_Del) ! ELIUK: aqui se decide si se pone mayuscula o no if (flag) { print "D"; } ! 'flag' activado else { print "d"; } ! 'flag' desactivado if (obj has proper) { ! 030305 print "e "; ! si es nombre propio, poner 'e' final... rtrue; ! ... y terminar la ejecucion aqui } #ifdef TARGET_ZCODE; texto_impreso-->0 = 50; @output_stream 3 texto_impreso; print (the)obj; @output_stream -3; if (texto_impreso->2 ~= 'e') { print "e "; } ! si NO ES articulo "el", agregar 'e' y un espacio #ifnot; !TARGET_GLULX PrintAnyToArray(texto_impreso, 50, PrefaceByArticle, obj, 1, -1); if (texto_impreso->0 ~= 'e') { print "e "; } ! si NO ES articulo "el", agregar 'e' y un espacio #endif; ! ahora imprimimos el articulo PrefaceByArticle(obj, 1, -1); ]; ! Con "al" el truco es más complejo, ya que si el artículo impreso por ! el_ empieza por "e", hay que cambiar esta "e" por una "a". Y si no ! empieza por "e" hay que poner una "a" delante. ! Además debemos capturar el caso de que no se imprima artículo alguno ! (si el objeto proporciona una propiedad "articulos" con cadenas ! vacías). !------------------------------------------------------------------------------ ! ELIUK BLAU: He re-implementado la rutina para permitir que la primera letra ! se imprima en mayuscula si se activa el argumento 'flag' durante la llamada. [ al_ obj flag; ! ELIUK: 'flag' es usado solo por rutina de impresion (_Al) #ifdef TARGET_ZCODE; texto_impreso-->0 = 50; @output_stream 3 texto_impreso; print (the) obj; @output_stream -3; ! print "^ ";for (i=2:i<50:i++) print (char)texto_impreso->i;print " "; ! infsp debug #ifnot; !TARGET_GLULX ! PrintAnyToArray(texto_impreso, 50, PrefaceByArticle, obj, 1, -1); PrintAnyToArray(texto_impreso, 50, Defart, obj);! 070809 infsp fix: corrige mal funcionamiento con Propios - gracias Eliuk ! print "^ ";for (i=0:i<2:i++) print (char)texto_impreso->i;print " "; ! infsp debug #endif; !TARGET_ ! ELIUK: aqui se decide si se pone mayuscula o no if (flag) { print "A"; } ! 'flag' activado else { print "a"; } ! 'flag' desactivado ! ELIUK: completamos el resto del texto que se imprimira finalmente #ifdef TARGET_ZCODE; if (texto_impreso->2 == 'e') { print "l "; } else { print " "; if (obj hasnt proper) { PrefaceByArticle(obj, 1, -1); } } #ifnot; !TARGET_GLULX if (texto_impreso->0 == 'e') { print "l "; } else { print " "; if (obj hasnt proper) { PrefaceByArticle(obj, 1, -1); } } #endif; !TARGET_ ]; [ del obj; print (del_) obj; print (name) obj; ]; ! ELIUK BLAU: Rutina de impresion "De", "Del", "De la", "De los", "De las" con la primera ! letra en mayuscula. Se usa como base el funcionamiento de la rutina del_() de INFSP. [ _Del obj; del_(obj,1); ! con 1 se activa 'flag' para imprimir primera letra en mayuscula print (name) obj; ! NOTA: SI POSTERIORMENTE SE INTENTA MEJORAR ESTA RUTINA, JUNTO CON del_(), ! LA SOLUCION JAMAS DEBE SER IMPRIMIR A UN BUFFER PORQUE LOS RESULTADOS ! PUEDEN SER INESPERADOS. LA PROPIA del_() YA IMPRIME A UN BUFFER, ASI QUE ! OTRO TRABAJO DEL MISMO TIPO IMPLICARIA TENER QUE CREAR UN NUEVO ARRAY ! CON EL QUE TRABAJAR O USAR EL ARRAY COMUN StorageForShortName DE LA ! PROPIA LIBRERIA INFORM. EN ESTE ULTIMO CASO ES CUANDO SE PRODUCEN LOS ! PROBLEMAS... POR OTRO LADO: CREAR UN NUEVO ARRAY SOLO PARA QUE LO USE ! ESTA RUTINA NO TIENE SENTIDO. POR ESO LA NECESIDAD DEL 'flag' EN del_() ]; [ al obj; print (al_) obj; print (name) obj; ]; ! ELIUK BLAU: Rutina de impresion "A", "Al", "A la", "A los", "A las" con la primera ! letra en mayuscula. Se usa como base el funcionamiento de la rutina al_() de INFSP. [ _Al obj; al_(obj,1); ! con 1 se activa 'flag' para imprimir primera letra en mayuscula print (name) obj; ! NOTA: SI POSTERIORMENTE SE INTENTA MEJORAR ESTA RUTINA, JUNTO CON al_(), ! LA SOLUCION JAMAS DEBE SER IMPRIMIR A UN BUFFER PORQUE LOS RESULTADOS ! PUEDEN SER INESPERADOS. LA PROPIA al_() YA IMPRIME A UN BUFFER, ASI QUE ! OTRO TRABAJO DEL MISMO TIPO IMPLICARIA TENER QUE CREAR UN NUEVO ARRAY ! CON EL QUE TRABAJAR O USAR EL ARRAY COMUN StorageForShortName DE LA ! PROPIA LIBRERIA INFORM. EN ESTE ULTIMO CASO ES CUANDO SE PRODUCEN LOS ! PROBLEMAS... POR OTRO LADO: CREAR UN NUEVO ARRAY SOLO PARA QUE LO USE ! ESTA RUTINA NO TIENE SENTIDO. POR ESO LA NECESIDAD DEL 'flag' EN al_() ]; [ lo obj gna; gna=GetGNAOfObject(obj); switch(gna) { 0,6: print "lo"; 1,7: print "la"; 3,9: print "los"; 4,10: print "las"; } ]; ! Cuando el usuario teclea un comando incompleto, es necesario que ! el parser genere un mensaje preguntando por lo que falta, ! pero la forma de preguntarlo depende del verbo. Por ej.: ! ! > coge ! ¿Qué quieres coger? ! ! > mete llave ! ¿Dónde quieres meter la llave? ! ! > orco, saca la botella ! ¿De dónde tiene que sacar el orco la botella? ! ! Cuando el parser tiene que imprimir una respuesta de estas, ! simplemente llama a MLIdioma con el número de mensaje Misc, 48 o ! 49. En esta versión de la librería (6/7) es responsabilidad de ! LanguageLM generar el mensaje completo. ! ! En nuestro caso hemos implementado estos mensajes de forma que ! llaman a IniciarPregunta para que escriba una partícula interrogativa ! como "Donde" "De donde", etc. Si no escribe nada, MLIdioma pone ! "Qué" o "A quién" según el tipo de error, a continuación se escribe ! "quieres" o "tiene que" según quién sea el actor. Se llama a ! LanguageVerb para que escriba el verbo, y finalmente se añade el ! name del objeto directo si lo había, para terminar la pregunta ! cerrando la interrogación. ! ! IniciarPregunta, lo que hace es: ! ! 1) busca preposiciones en el patrón que ha encajado, si las ! encuentra, la pregunta debe comenzar por alguna partícula ! interrogativa. Por ejemplo, si la línea de gramática hallada era ! "saca" noun "de" noun, se hallará la preposición "de" que nos indica ! que la pregunta ha de comenzar con "¿De dónde ...". ! ! 2) Llama a la función "IdiomaPreguntarPrep" que recibe como ! parámetros la preposición y la acción en curso, para que imprima la ! partícula interrogativa adecuada. Esta función tan sólo debe ! escribir esa partícula. ! ! IdiomaPreguntarPrep llama a su vez a PreguntarPreposicion por si el ! programador añade verbos raros con preposiciones raras que no son ! correctamente manejados por esta rutina. Si PreguntarPreposicion ! existe y retorna distinto de cero, IdiomaPreguntarPrep asumirá ! que la partícula interrogativa ya ha sido escrita por ! PreguntarPreposicion y no hará nada más. ! [ IdiomaPreguntarPrep prepos action; if (PreguntarPreposicion(prepos, action)) return; ! print "^IPPrep: action: ", (DebugAction)action, " Prepos: ",(address)prepos,"^"; ! infsp debug switch (prepos) { 'de': print "De dónde"; 'en', 'dentro', 'encima': print "Dónde"; 'bajo','debajo':print "Debajo de qué"; 'sobre', 'acerca':print "Sobre qué"; 'contra': print "Contra qué"; 'hacia':print "Hacia dónde"; 'con':if (action==##Tell or ##Attack) print "Con quién"; else print "Con qué"; 'por':if (action==##Ask) print "Por qué"; else print "Por dónde"; 'una', 'un' : print "A quién"; ! #n$a: switch(action) ! esto es arcaico man! 'a//': switch(action){ ##Go: print "Hacia dónde"; ##GoIn, ##Climb: print "Dónde"; ##ThrowAt, ##Give, ##Show, ##Answer, ##Tell, ##Ask: print "A quién"; ##Search: print "A través de qué"; ##Tie: print "A qué"; ##Transfer,##Enter: print "A dónde"; default: print "A quién"; }; } ]; ! A partir del patrón que ha construido el parser, se determina cuál ! es la primera preposición usada detrás del verbo. ! Esto será usado por la función IniciarPregunta y por LanguageIsVerb ! [INFSP] Recoding para un mejor comportamiento en caso de lineas de gramaticas complejas ! Ej: 'pon' noun 'en/sobre' noun . Antes usando 'sobre' (segundo token) no andaba. ! (devolvia NULL) [ AveriguarPreposicion i k p ; ! print " ",pattern-->(pcount-1)," ^"; ![infsp] debug p = NULL; for (k=pcount:k>=1:k--){ ! print "^AP: k:",k; ! infsp debug i=pattern-->k; ! print "^ i:",(address)No__Dword(i-REPARSE_CODE); ! infsp debug if ( i == PATTERN_NULL) continue; if (i>=REPARSE_CODE) p=No__Dword(i-REPARSE_CODE); } return p; ]; [ AveriguarPrimeraPreposicion i k p found; p=NULL; for (k=pcount:k>=1:k--) { ! print "^AP: k:",k; ! infsp debug i=pattern-->k; ! print "^ i:",i; ! infsp debug if (pattern-->k == PATTERN_NULL) continue; ! i=pattern-->k; if (i>=REPARSE_CODE) { i=No__Dword(i-REPARSE_CODE); p=i; ! nos quedamos con la primera found=k; } } ! print "APP: Primera prep: ",(address) p; ! infsp debug ! print " / found :",found; ! infsp debug ! print " / pcount :",pcount,"^"; ! infsp debug if (found==(pcount -1)) return NULL; else return p; ]; ! Averigua si es necesaria una partícula interrogativa. Llama a ! IdiomaPreguntarPrep para que la imprima. ! ! Retorna 1 si ha sido impresa la partícula interrogativa, y 0 en caso ! contrario, (y entonces la función que la llamó "LanguageLM", sabe ! que es necesario escribir "Qué" o "A quién" ya que en este caso lo ! que faltaba era el objeto directo en lugar del complemento. ! [ IniciarPregunta p; print "¿"; p=AveriguarPreposicion(); if (p~=NULL) { IdiomaPreguntarPrep(p, action_to_be); return 1; } return 0; ]; [ IdiomaImprimirComando from i k spacing_flag prep; if (from==0) { i=verb_word; LanguageVerb(i); from++; spacing_flag = true; } ! print "^Valor de from: ",from,"^"; ! infsp debug ! print "Valor de pcount: ",pcount,"^"; ! infsp debug for (k=from:kk; ! print "^IIC: i: ", i, "^"; ! infsp debug if (i == PATTERN_NULL) continue; ! if (spacing_flag) print (char) ' '; if (i == 0 ) { print " ",(string) THOSET__TX; jump TokenPrinted; } if (i == 1) { print " ",(string) THAT__TX; jump TokenPrinted; } if (i >= REPARSE_CODE) continue; else { if (i in compass && LanguageVerbLikesAdverb(verb_word)) LanguageDirection (i.door_dir); ! the direction name as adverb if (i==player) print "te"; else { prep=AveriguarPrimeraPreposicion(); switch(prep){ 'a//': print " ",(al) i; 'de': print " ",(del) i; NULL: print " ",(the) i; default: !print " ", (address) prep; print " ",(the) i; } } continue; } .TokenPrinted; spacing_flag = true; } ! for ]; ! [001115] ! Los mensajes de librería van ahora en fichero aparte ! [010515] Cambiado de sitio el punto de inclusión de Mensajes.h ! para dar la oportunidad al usuario de incluir su propio Mensajes ! si lo desea (antes del include Gramatica) ! Include "Mensajes"; [ LanguagePrintShortName obj aux; aux=aux; if (obj provides gender) { if (parser_trace>=10) print "[", obj, " tiene ~genero~=", obj.gender, ".]^"; #ifdef DEBUG; aux=debug_flag; debug_flag=0; #endif; switch(obj.gender) { 1: give obj ~female ~pluralname; !infsp fix for I7 compatibility (en I7 no se puede asignar el 0 a gender, de 1 para arriba si) 2: give obj female ~pluralname;!print " FEMALE GIVEN "; !infsp debug 3: give obj ~female pluralname; 4: give obj female pluralname; } #ifdef DEBUG; debug_flag=aux; #endif; rfalse; } else{ ! if (parser_trace>=10) ! print "[", obj, " no tiene la propiedad ~genero~.]"; rfalse; } ]; ! Esta función de elegir objetos asigna más puntuación al objeto que ! ha sido llamado por su 'name' (por tanto toman prioridad sobre los ! que son llamados solo por su 'adjetivo'). Se excluye al propio ! player de la lista, y los objetos de scenery. Solo para inform 6 ! Inform 7 tiene su propio ChooseObjects, ver Cap 16.16 [ ChooseObjects obj codigo prio; ! prio=ChooseObjects2(obj,codigo); ! [TODO] si ChooseObjects estuviera usada por otra libreria, retocar aqui ! print "^[ElijeObjetos : priority = ",prio," (initial)"; ! infsp debug if (codigo>=2){ if (obj has nombreusado){ !levantar prioridad al objeto mencionado en ultimo turno if (bandera_todo_vale==0) prio=prio+10;! bandera_todo_vale?????? infsp crazy freak question:de donde salio? } if ((obj == player)||((obj has scenery)&&(obj notin compass))) prio=prio-10; } ! print " priority = ",prio, " (last)"; ! infsp debug return prio; ]; !=============================================================================== ! INICIO: Seccion Mensajes V0.8 Edicion Inicial 070905 ! Creada a partir de Mensajes.h (InformATE) ! ! NOTA DE ELIUK BLAU (a partir de R712.6): ! Si se define la constante de compilacion condicional SIN_MENSAJES, ! entonces no se incluiran en el codigo del juego los mensajes estandares ! de la libreria. De esta manera se le permite al programador implementar ! sus propios mensajes de la libreria en el codigo del juego o mediante ! alguna libreria de extension. Recuerda que si solo vas a redefinir unos ! pocos mensajes y no todos es siempre mejor usar el mecanismo de ! "LibraryMessages". Consulta el manual de Inform para mayores detalles. !------------------------------------------------------------------------------- #ifdef SIN_MENSAJES; Message "> Spanish: AVISO - Omitiendo los mensajes estandares de la libreria"; #ifnot; Constant FORMER__TX = "tu antiguo ~yo~"; Constant YOURSELF__TX = "ti mismo"; Constant CANTGO__TX = "No puedes ir por ahí."; Constant IS__TX = " ves"; Constant ARE__TX = " ves"; Constant IS2__TX = "ves "; Constant ARE2__TX = "ves "; Constant YOU__TX = "Tú"; Constant PARTICULA_TE = "te"; [ LanguageLM n x1; ! Answer: " ",(The) second , " no te responde."; ! esto sera sólo para I6? Answer, Ask : "No hay respuesta."; ! Ask: " ",(The) x1 , " no te responde."; ! Ask: see Answer Attack: "La violencia no es la solución."; Blow: "Tu soplido no produce ningún efecto."; Burn: "Con esa peligrosa acción no lograrías nada."; Buy: "No hay nada en venta."; Climb: "No creo que vayas a lograr nada así."; Close: switch(n) { 1: print_ret "No es algo que pueda cerrarse."; 2: "Ya estaba", (n) x1, " cerrad", (o)x1, "."; 3: "Cierras ", (the) x1, "."; } CommandsOff: switch (n) { ![6/11] 1: "[Grabación de órdenes finalizada.]"; #Ifdef TARGET_GLULX; 2: "[Grabación de órdenes ya estaba finalizada.]"; #Endif; ! TARGET_ } CommandsOn: switch (n) { ! [6/11] 1: "[Grabación de órdenes activada.]"; #Ifdef TARGET_GLULX; 2: "[Órdenes relanzadas.]"; 3: "[Grabación de órdenes ya activada.]"; 4: "[Fallo en la grabación de órdenes.]"; #Endif; ! TARGET_ } CommandsRead: switch (n) { ! [6/11] 1: "[Relanzando acciones.]"; #Ifdef TARGET_GLULX; 2: "[Las órdenes ya están siendo relanzadas.]"; 3: "[Fallo en la reejecución de órdenes: grabación en curso.]"; 4: "[Fallo en la reejecución de órdenes.]"; 5: "[Acciones ejecutadas: fin del proceso.]"; #Endif; ! TARGET_ } Consult: "No descubres nada interesante en ", (the) x1, " sobre ese tema."; Cut: "Cortándo", (lo) x1, " no lograrás gran cosa."; Dig: "Excavar no servirá de nada aquí."; Disrobe: switch(n) { 1: "No llevas puesto eso."; 2: "Te quitas ", (the) x1, "."; } Drink: "Eso no parece potable."; Drop: ! 2 mensajes de error, 1 aviso y 1 de éxito: ! 1: Error, el objeto dejado no está en poder del jugador, pero ! está en la localidad. ! 2: Error, el objeto dejado no está en poder del jugador ni en ! la localidad. ! 3: Aviso, el objeto era una prenda que el jugador llevaba ! puesta y la librería va a quitarsela automáticamente para ! poder dejarla. ! 4: Exito switch(n) { 1: "Para dejar ", (the)x1, " deberías tener", (lo) x1, "."; 2: "No ", (lo) x1, " tienes."; 3: "(primero te quitas ", (the) x1, ")"; 4: "Dejad", (o) x1, "."; } Eat: ! 1: Error, el objeto no tiene el atributo "comestible" ! 2: Exito. [NOTA: la librería permite por defecto comerse ! cualquier cosa que tenga el atributo "comestible", pero la ! única acción que causa esto es que el objeto en cuestión ! desaparece del juego al ser comido] switch(n) { 1: "Eso es simplemente incomestible."; 2: "Te comes ", (the) x1, ". No está mal."; } EmptyT: ! 1: Error, el jugador intenta vaciar un objeto en otro que no es ! un recipiente. ! 2: Error, el jugador intenta vaciar un objeto sobre un ! recipiente cerrado. ! 3: Error, el jugador intenta vaciar un objeto que no tiene nada ! dentro. ! 4: Error, el jugador intenta vaciar un objeto sobre sí mismo. ! [NOTA: No hay mensajes de éxito para esta acción, ya que en caso ! de haber superado los test anteriores, la librería genera ! finalmente la acción Transferir, la cual a su vez, generará la ! acción PonerSobre o Meter, según el segundo objeto sea soporte o ! recipiente. Por tanto los mensajes de éxito serán los de las ! acciones PonerSobre o Meter. switch(n) { 1: print_ret (The) x1, " no puede tener cosas dentro."; 2: print_ret (The) x1, " ", (esta) x1, " cerrad", (o) x1, "."; 3: print_ret (The) x1, " ya ", (esta) x1, " vací", (o)x1, "."; 4: "No puedes vaciar un objeto sobre sí mismo."; ! [INFSP] antes usaba x1 } Enter: ! [infsp] GoIn (Meterse) se cambio por Enter. ! CUIDADO. La acción Meterse se genera en muy diversas ! circunstancias: VETE HACIA EL PUENTE, VETE AL PUENTE, VETE POR ! EL PUENTE, PASA POR EL PUENTE, ENTRA EN EL PUENTE, ENTRA AL ! PUENTE, CRUZA EL PUENTE, CRUZA POR EL PUENTE, METETE EN EL ! PUENTE, METETE POR EL PUENTE, ATRAVIESA EL PUENTE, BAJA POR EL ! PUENTE. Todas ellas generarían la acción ! ! Además, los intentos de entrar en un "entrable", también, como ! por ejemplo: SIENTATE EN EL BANCO, ECHATE EN EL BANCO, SUBETE AL ! BANCO, SUBETE EN EL BANCO, SUBE AL BANCO, SUBE POR EL BANCO, ! SALTA AL BANCO. Todas ellas generarían ! ! Puesto que hay muchos verbos diferentes que dan lugar a la misma ! acción, es necesaria alguna forma de imprimir qué verbo concreto ! ha sido el que la ha desencadenado, para poder generar mensajes ! como "No puedes entrar ahi", "No puedes sentarte ahi", "No ! puedes subirte ahi", etc.. según el verbo usado. Para esto puede ! usarse una llamada a IdiomaVerbo(palabra_verbo). palabra_verbo ! contiene el verbo usado por el jugador (convertido en forma ! imperativa), y IdiomaVerbo lo que hace es imprimir la forma ! infinitiva. ! ! Mensajes que puede generar esta acción: ! 1: Error, el jugador ya está en/sobre el objeto en cuestión ! 2: Error, el objeto al que intenta entrar/subirse/meterse no ! tiene el atributo "entrable" ! 3: Error, el objeto en que intenta entrar/meterse/subirse, es ! un entrable y recipiente, pero está cerrado. ! 4: Error, el objeto en que intenta entrar/meterse/subirse, está ! en poder del jugador ! 5: Exito, el jugador sube/entra en el objeto ! 6: Aviso, el jugador estaba en otro objeto, la librería ! intentará una acción automática, antes de reintentar lo ! que el jugador le ha ordenado. ! 7: Aviso, el objeto en que el jugador intenta meterse, está ! dentro de otros objetos. La librería intentará de forma ! automática meter al jugador en el objeto desde el cual pueda ! acceder al que el jugador ha indicado. switch(n) { 1: print "Pero si ya estás "; if (x1 has supporter) print "sobre "; else print "en "; print_ret (the) x1, "."; 2: print "No es algo donde puedas "; LanguageVerb(verb_word); "."; 3: "No puedes entrar en ", (the) x1, " porque está", (n) x1, " cerrad", (o) x1, "."; 4: print "No puedes "; LanguageVerb(verb_word); " ahí mientras no lo sueltes."; 5: if (x1 has supporter) print "Subes ", (al) x1; else print "Entras en ", (the) x1; print_ret "."; 6: if (x1 has supporter) print "(te bajas "; else print "(sales "; print (del) x1; ")"; 7: if (x1 has supporter) "(te subes ", (al) x1, ")^"; if (x1 has container) "(te metes en ", (the) x1, ")^"; "(entras en ", (the) x1, ")^"; } Examine: ! 1: Error, el jugador intenta examinar un objeto, pero está a ! oscuras. ! 2: Exito, pero el objeto examinado no tiene descripcion ! 3: Exito, pero el objeto examinado no tiene descripcion, aunque ! tiene el atributo conmutable, por lo que la librería genera ! este mensaje para indicar si está apagado o encendido. switch(n) { 1: "Está demasiado oscuro, no puedes ver nada."; 2: "No observas nada especial en ", (the) x1, "."; 3: print (The) x1, " ", (esta) x1; if (x1 has on) " encendid", (o)x1, "."; else " apagad", (o)x1,"."; } Exit: ! 1: Error, el jugador no está subido/sentado/metido en ningún ! objeto. [Nota, si la localidad tiene la propiedad "afuera", ! entonces la acción Salir lo sacará de la localidad. En caso ! contrario es cuando se genera este error] ! 2: Error, el jugador está dentro de un recipiente cerrado. ! 3: Exito, el jugador sale/baja del objeto ! 4: Error, mas especifico. [6/11] switch(n) { 1: print "No estás en ningún sitio del que debas "; LanguageVerb(verb_word); "."; 2: "No puedes salir ", (del) x1, " porque está cerrad", (o)x1, "."; 3: if (x1 has supporter) print "Bajas "; else print "Sales "; print_ret (del) x1, "."; 4: print "Pero es que no estás "; if (x1 has supporter) print "encima de "; else print "dentro de "; print_ret (the) x1, "."; } Fill: "No puedes llenar", (lo) x1, "."; FullScore: ! Puntuación en modo "explicativo". Puede activarse porque el ! jugador lo pida con el verbo "PUNTUACION LARGA" o porque el ! juego haya terminado (y la constante HAY_TAREAS está definida). ! ! 1: texto introductorio al desglose de puntos ! 2: texto de objetos importantes (los que tienen el atributo ! "valepuntos") ! 3: texto de lugares importantes (los que tienen el atributo ! "valepuntos") ! 4: texto final, tras la suma total impresa por la librería switch(n) { 1: if (deadflag) print "La puntuación se desglosó "; else print "La puntuación se desglosa "; "de la siguiente manera:^"; 2: "por encontrar objetos importantes"; 3: "por visitar lugares importantes"; 4: print "total (de ", MAX_SCORE ; ")"; } GetOff: ! Esta acción se genera ante la frase SAL DEL ARMARIO o ! similares. Ante SAL a secas la acción es Salir. ! Si el jugador no está en el objeto indicado, se genera el ! siguiente mensaje de error. Si está, la librería generará una ! acción Salir, por lo que el mensaje de éxito será el de Salir. "Pero si no estás en ", (the) x1, "."; Give: ! 1: Error, el jugador intenta dar un objeto que no tiene ! 2: Error, el jugador se da el objeto a sí mismo ! 3: Aviso, se ha enviado la acción Dar al PNJ, pero este no ha ! respondido. En este caso ml_o apunta al PNJ y no al objeto ! que le hemos dado. ! [Observar que por defecto el objeto sigue en poder del ! jugador. Si queremos que el PNJ lo acepte, hay que programarlo ! como parte de su rutina Vida] switch(n) { 1: "No tienes ", (the) x1, "."; 2: "Manoseas ", (the) x1, " un ratito, pero no consigues gran cosa."; 3: print_ret (The) x1, " no parece", (n) x1, " interesad", (o)x1, "."; } Go: ! La acción Ir se genera si el jugador pone IR NORTE, o si pone ! simplemente NORTE. ! 1: Error, el jugador está dentro/subido en un objeto del que ! tiene que salir antes ! 2: Error, la localidad no tiene salida en esa dirección (y ! tampoco tiene la propiedad no_puedes_ir, ya que en este caso ! se habría impreso el valor de esa propiedad ! 3: Error, el jugador ha intentado ir hacia arriba, pero allí ! hay una puerta cerrada ! 4: Error, el jugador ha intentado ir hacia abajo, pero alli ! hay una puerta cerrada. ! 5: Error, en la dirección que ha dicho el jugador hay una ! puerta cerrada ! 6: Error, en la dirección que ha dicho el jugador hay una ! puerta, pero ésta no tiene una propiedad puerta_a ! (probablemente un error de programación del juego) switch(n) { 1: print "Tienes que "; if (x1 has supporter) print "bajarte "; else print "salir "; print_ret (del) x1, " antes."; 2: "No puedes ir por ahí."; 3: "Eres incapaz de trepar por ", (the) x1, "."; 4: "Eres incapaz de bajar por ", (the) x1, "."; 5: "No puedes pasar a través ", (del) x1, "."; 6: "No puedes ir porque ", (the) x1, " no lleva", (n) x1, " a ningún sitio."; } Insert: ! 1: Error, el objeto no está en poder del jugador. [Nota, ! conviene mirar en este caso si el objeto es animado o no, ! para generar un mensaje más adecuado] ! 2: Error, el jugador intenta meter el objeto en otro que no ! tiene el atributo "recipiente" ! 3: Error, el jugador intenta meter el objeto en un recipiente ! cerrado. ! 4: Error, el objeto es una prenda que el jugador lleva puesta. ! [ESTE MENSAJE NO SE GENERA NUNCA, PARECE UN BUG DE LA ! LIBRERIA. Véase en su lugar el mensaje 6] ! 5: Error, se intenta poner un objeto dentro de sí mismo ! 6: Aviso, el objeto es una prenda puesta, la librería va a ! quitársela de forma automática antes de reintentar Meter. ! 7: Error, no queda sitio en el recipiente (el número de objetos ! que un recipiente puede contener se indica en su propiedad ! "capacidad"). ! 8: Exito. Mensaje a mostrar para cada objeto metido cuando se ! meten muchos (ej: METE TODO EN LA BOLSA) ! 9: Exito. Mensaje a mostrar cuando se mete un solo objeto dentro ! de otro switch(n) { 1: if (x1 has animate) "Antes tendrías que ", (coge)"rl", (o) x1, " y no sé si se dejará",(n)x1,"."; else "Necesitas tener ", (the) x1, " para poder meter", (lo) x1, " donde sea."; 2: "No se pueden meter cosas dentro ", (del) x1, "."; 3: print_ret (The) x1, " ", (esta) x1, " cerrad", (o) x1, "."; 4: "Tienes que quitarte", (lo) x1, " antes."; 5: "No puedes poner un objeto dentro de sí mismo."; 6: "(primero te ", (lo) x1, " quitas)^"; 7: "No queda sitio en ", (the) x1, "."; 8: "Hecho."; 9: "Metes ", (the) x1, " dentro ", (del) second, "."; } Inv: ! Inventario ! 1: Mensaje si el inventario está vacío ! 2: Encabezado del inventario, antes de la lista de objetos ! generada por la librería ! 3 y 4: [6/11] switch(n) { 1: "No llevas nada."; 2: print "Llevas"; 3: print ":^"; 4: print ".^"; } Jump: "Saltas en el sitio, sin ningún resultado."; JumpOver,Tie: "No lograrás nada así."; Kiss: "No creo que debas."; Listen: "No escuchas nada fuera de lo común."; ListMiscellany: ! Los siguientes mensajes se muestran como aclaraciones cuando se ! está listando el inventario del jugador, o los objetos que hay ! en una localidad. Junto a cada mensaje se comenta qué ! condiciones deben darse en ese objeto para que se muestre ese ! mensaje aclaratorio switch(n) { 1: print " (alumbrando)"; ! El objeto tiene "luz" y la localidad no 2: print " (que ", (esta) x1, " cerrad", (o) x1, ")"; ! El objeto tiene "recipiente" pero no "abierto" 3: print " (cerrad", (o) x1, " y alumbrando)"; ! Casos 2 y 1 juntos 4: print " (que ", (esta) x1, " vací", (o) x1, ")"; ! El objeto es un recipiente abierto (o transparente) y no ! tiene nada en su interior 5: print " (vací", (o) x1, " y alumbrando)"; ! Casos 1 y 4 juntos 6: print " (que ", (esta) x1, " cerrad", (o) x1, " y vací", (o) x1, ")"; ! El objeto tiene "recipiente", no "abierto", pero sí ! "transparente" 7: print " (cerrad", (o) x1, ", vací", (o) x1, " y alumbrando)"; ! Casos 1 y 6 juntos ! Los casos siguientes son similares, pero se muestran cuando ! se solicita a la rutina EscribirListaDesde la opcion INFOTOTAL ! La librería puede combinar varios de estos mensajes, por eso no ! deben llevar el cerrar paréntesis al final, que lo añade la ! propia librería ! ************************************ ! NO SE ACONSEJA CAMBIAR ESTOS ! ************************************ 8: print " (alumbrando y que llevas puest", (o) x1; ! El objeto tiene "luz" y "puesto" 9: print " (alumbrando"; ! El objeto tiene "luz" pero no "puesto" 10: print " (que llevas puest", (o) x1; ! El objeto tiene "puesto" pero no "luz" 11: print " (que ", (esta) x1, " "; ! Mensaje introductorio para decir "que está ! abierto/cerrado/vacio"... 12: print "abiert", (o)x1; ! Objeto tiene "recipiente", "abrible" y "abierto" (y cosas dentro) 13: print "abiert", (o)x1, ", pero vací", (o) x1; ! Objeto tiene "recipiente", "abrible" y "abierto (pero vacio) 14: print "cerrad", (o) x1; ! Objeto tiene "recipiente", "abrible" y no "abierto" 15: print "cerrad", (o) x1, " con llave"; ! Objeto tiene "recipiente", "abrible" y "cerrojoechado" o "cerrojo" 16: print " vací", (o) x1; ! Objeto tiene "recipiente", no "abrible" y "transparente" 17: print " (que ", (esta) x1, " vací", (o) x1, ")"; ! Como el caso anterior, pero mensaje más "largo" (que se activa si ! EscribirListaDesde es llamada sin el modo BREVE_BIT) 18: print " que contiene "; ! encabezado a la lista de lo que hay dentro del objeto 19: print " (sobre ", (el_) x1; ! Si el objeto tiene "soporte", la librería va a listar sus ! contenidos. Este es el encabezado de la lista 20: print ", encima ", (del_) x1; ! Como e l9, pero en otra modalidad (que se activa si ! EscribirListaDesde es llamada sin el modo BREVE_BIT) 21: print " (en ", (el_) x1; ! Si el contenido tiene "recipiente" y puede verse su interior ! y hay cosas, la librería va a mostrar sus contenidos. Este ! es el encabezado de la lista 22: print ", dentro ", (del_) x1; ! Como el 21, pero en otra modalidad (que se activa si ! EscribirListaDesde es llamada sin el modo BREVE_BIT) } LMode1: ! La acción ModoM1 se genera ante el comando BREVE (o NORMAL). La ! librería imprime la constante Historia y a continuación este ! mensaje. " está ahora en su modo normal ~breve~, que da sólo descripciones largas de los lugares la primera vez que son visitadas, y descripciones cortas en otro caso."; LMode2: ! La acción ModoM2 se genera ante el comando LARGO. La ! librería imprime la constante Historia y a continuación este ! mensaje. " está ahora en su modo ~largo~, que siempre da descripciones largas de los lugares (incluso si ya habías estado antes)."; LMode3: ! La acción ModoM3 se genera ante el comando SUPERBREVE. La ! librería imprime la constante Historia y a continuación este ! mensaje. " está ahora en su modo ~superbreve~, que siempre da descripciones cortas de los lugares (incluso si nunca habías estado antes)."; Lock: ! EcharCerrojo se genera con CIERRA CON , o ! tambien ante ECHA CERROJO A . (sin especificar un ! segundo objeto en este caso) ! ! 1: Error, el objeto que se intenta cerrar no tiene la propiedad ! "cerrojo". ! 2: Error, el objeto que se intenta cerrar tiene la propiedad ! "cerrojo", pero ya tiene también "cerrojoechado ! 3: Error, el objeto tiene "cerrojo", pero está "abierto". No se ! le puede echar el cerrojo hasta que no se cierre. ! 4: Error, el especificado no coincide con el que el ! indica en su propiedad "con_llave". ! 5: Exito, el es cerrado (con si este es ! specificado, el cual puede encontrarse en la variable ! "otro") switch(n) { 1: "No parece", (n) x1, " tener ningún tipo de cerrojo."; 2: if (x1 provides with_key) print_ret (The) x1, " ya estaba", (n) x1, " cerrad", (o) x1, " con llave."; else print_ret (The) x1, " ya tiene",(n) x1, " echado el cerrojo."; 3: "Primero tendrás que cerrar ", (the) x1, "."; 4: if (second) "No parece", (n) x1, " encajar en la cerradura."; "Necesitas algún tipo de llave."; 5: if (second) "Cierras ", (the) x1," con ", (the) second, "."; "Echas el cerrojo ", (al) x1, "."; } Look: ! La acción Look se genera cuando el player pone MIRAR, pero ! también de forma automática al entrar en una localidad nueva, o ! cuando el player sale/se baja de un objeto en el que estaba. ! ! Algnouns de los mensajes que se definen aqui aparecen en el ! "título" de la localidad (lo que aparece en negrita before de la ! descripción de la localidad) ! ! 1: aclaración a añadir tras el título si el player está subido ! en un objeto ! 2: aclaración a añadir tras el título si el player está dentro ! de un objeto ! 3: aclaración a añadir tras el título si el player ha sido ! transformado en otro personaje, mediante una llamada a ! ChangePlayer(nuevo, 1); (si el 1, la librería no intentará ! mostrar este mensaje) ! 4: Una vez que la librería ha mostrado la descrcipción de la ! localidad, si el player estaba encima de un supporter, la ! librería generará este mensaje 4 para mostrar qué más cosas ! hay sobre el supporter ! Restante: 5,6 [6/11] antes 'default' ! Son usados por la librería para listar los objetos "simples" ! que hay en la localidad. Son objetos "simples" los que no ! dan su propia auto-descrcipcion a través de la propiedad ! "describe" o "initial". ! 7: Respuesta estandar para MirarHacia [6/11] switch(n) { 1: print " (sobre ", (the) x1, ")"; 2: print " (en ", (the) x1, ")"; 3: print " (como ", (object) x1,")"; 4: print "^Sobre ", (the) x1; ! ELIUK: agregado salto de linea inicial (solo I6) WriteListFrom(child(x1), ENGLISH_BIT + RECURSE_BIT + PARTINV_BIT + TERSE_BIT + ISARE_BIT + CONCEAL_BIT); "."; 5,6: new_line; ! ELIUK: agregado salto de linea inicial (solo I6) if (x1~=location) { if (x1 has supporter) print "Sobre "; else print "En "; print (the) x1; print " puedes ver "; } else print "Puedes ver "; if (n==5) print "también "; WriteListFrom(child(x1), ENGLISH_BIT + WORKFLAG_BIT + RECURSE_BIT + PARTINV_BIT + TERSE_BIT + CONCEAL_BIT); if (x1~=location) "."; "."; 7: "No observas nada digno de mención al mirar hacia ", (the) x1, ".";![6/11] ! ELIUK: sobraba el "más" 8: if (x1 has supporter) print " (sobre "; else print " (en "; ! added in 6/11N 4U65 print (the) x1, ")"; } LookUnder: ! Dos casos: ! 1: Error, estamos a oscuras ! 2: Exito, mensaje por defecto. switch(n) { 1: "Está muy oscuro."; 2: "No ves nada interesante."; } Mild: "Bastante."; ! Y esta si usa como primera palabra algún insulto más suave !================================================================ ! MISCELANEA !================================================================ ! Esta es una falsa acción, que se usa simplemente para agrupar aquí ! todos los mensajes de error del parser, los mensajes ante algunos ! metacommandos, o algnouns mensajes de librería no relacionados con ! acción alguna. La asignación de números a mensajes es bastante ! caprichosa. ! Debajo de cada mensaje un comentario indica en qué condiciones se ! genera. Miscellany: switch(n) { 1: "(Sólo considero los dieciséis primeros objetos)^"; ! El player ha especificado objetos multiples, pero el parser ! tiene una lista que no admite más de 16, de modo que los ! restbefore objetos no serán procesados. 2: "¡No sé a qué objetos te refieres!"; ! El player ha usado objetos multiples, pero por alguna razón ! la lista del parser está vacía. 3: ! TextoLlamativo(" Has muerto "); print " Has muerto "; ! Mensaje fin de juego. Has muerto. 4: ! TextoLlamativo(" Has ganado "); print " Has ganado "; ! Mensaje fin de juego de victoria. 5: ! Mensaje a mostrar tras el fin del juego, para pedir al ! player si quiere reniciar, recuperar, anular, puntuación, ! curiosidades o terminar. print "^¿Quieres REINICIAR, RECUPERAR un juego guardado"; #IFDEF DEATH_MENTION_UNDO; print ", ANULAR tu último movimiento"; #ENDIF; ! #IFNDEF NO_PUNTUACION; if (TASKS_PROVIDED==0) print ", ver la PUNTUACIÓN de este juego"; ! #ENDIF; ! NO_PUNTUACION if (deadflag==2 && AMUSING_PROVIDED==0) print ", ver algunas CURIOSIDADES"; " o TERMINAR?"; 6: "[Tu intérprete no puede ~deshacer~ acciones, ¡lo siento!]"; ! Error si el intérprete no tiene "undo" #Ifdef TARGET_ZCODE; ![6/11] 7: "~deshacer~ falló. [No todos los intérpretes lo tienen.]"; #Ifnot; ! TARGET_GLULX 7: "[No puedes ~deshacer~ más.]"; #Endif; ! TARGET_ ! Otro error si el intérprete no tiene "undo", pero no había ! sido detectado correctamente 8: "Por favor, da una de las respuestas anteriores."; ! Si el player no responde correctamente a la pregunta del ! mensaje [Miscellany,5] 9: "^¡Te has quedado a oscuras!"; ! ELIUK: agregado salto de linea inicial (solo I6) ! Mensaje cuando se detecta, al final del turno, que ya no hay ! light. 10: "¿Perdón?"; ! Mensaje cuando el player introduce una linea en blanco (no ! llega a generarse acción alguna, por tanto no se consume ! turno ni se ejecutan daemons) 11: "[No puedes ~deshacer~ lo que no has hecho.]"; ! Si el player intenta "undo" al principio del juego 12: "[No puedes ~deshacer~ dos veces seguidas. ¡Lo siento!]"; ! Si el player pone "undo" dos veces 13: "[Retrocediendo al turno anterior.]"; ! Exito en el "undo" 14: "Lo siento, eso no puede corregirse."; ! Si el player pone EEPA (verbo para corregir), pero el ! parser no recordaba ninguna palabra mal ! El commando EEPA se usa así, por ejemplo: ! > SACA MAZANA VERDE DE LA CESTA ! No veo eso por aquí ! > EEPA MANZANA ! Sacas la manzana verde de la cesta de mimbre. 15: "No te preocupes."; ! Si el player pone EEPA sólo (sin especificar la palabra ! corregida) 16: "~eepa~ sólo puede corregir una palabra."; ! Si el player pone EEPA seguido de dos o más palabras 17: "Está muy oscuro y no puedes ver nada."; ! Descripción del objeto Oscuridad 18: print "ti mism", (o) player; ! Nombre corto del objeto player 19: "Tan buen aspecto como siempre."; ! Descripción del objeto player 20: "Para repetir un comando como ~rana, salta~, escribe ~repite~, en lugar de ~rana, repite~."; ! Cuando el player pone PNJ, REPITE para que el PNJ haga otra ! vez la última acción. 21: "No hay commando que repetir."; ! Cuando el player pone REPITE como primer commando del juego. 22: "No puedes empezar la frase con una coma."; ! Cuando ha empezado la frase con una coma :-) 23: "Parece que quieres hablar con alguien, pero no veo con quién."; ! Cuando el player pone PEPE, COGE HACHA, pero no hay un ! objeto que responda al name PEPE. 24: "No puedes hablar con ", (the) x1, "."; ! Si el player intenta hablar con un objeto que no es ! "animate" ni "talkable" ("talkable" debe ponerse a objetos ! inanimates con los que se podría hablar, como un micrófono) 25: "Para hablar con alguien intenta ~alguien, hola~ o algo así."; ! Si hay palabras no comprendidas entre el name del PNJ y ! la comma, como p.ej: PEPE XADASDGG, SALTA 26: "(primero tratas de ", (coge)"r ", (the) x1, ")"; ! infsp I6 ! Si la gramática especifica que una acción debe efectuarse ! sobre un objeto en poder del player (token "held"), pero el ! player lo intenta sobre un objeto que no tiene, pero que ! está accesible, el parser intentará automáticamente coger ! ese objeto antes de efectuar la acción. En este mensaje se ! avisa al player de esta intención. ! ================================================================ ! ERRORES DE PARSING ! Estos errores son generados por la librería, a menos que el ! programador proporcione su propia función ParserError para ! manejo de errores. 27:! El parser se ha atascado. Es el tipo de error más ! genérico. Si el parser puede, dará un error más concreto ! (noun de los siguientes) "No entendí esa frase."; 28:! Al parser le sobran palabras, aunque ha entendido gran parte ! de la orden. print "Intenta de nuevo, porque sólo te pude entender: "; 29: ! El parser esperaba un token de tipo número "No comprendí ese número."; 30: ! El parser no ha comprendido el nombre del objeto al que se ! refiere el player, o ese objeto no está aquí. "No veo eso que dices."; 31: ! Este error parece que no se genera nunca. Un posible bug de ! libreria, o restos de versiones arcaicas "¡Pareces haber dicho muy poca cosa!"; 32: ! El objeto que el player intenta usar no está en su ! poder. El parser ha intentado "cogerlo de forma automatica", ! pero ha fallado "¡No tienes eso!"; 33: ! El player ha intentado usar objetos múltiples (o "TODO") ! con un verbo que en su gramática no lo admite. "No puedes especificar objetos múltiples con ese verbo."; 34: ! El player ha intentado objetos multiples para "noun" y para ! "second", como en METE TODO EN TODO. "Sólo puedes especificar objetos múltiples una vez en cada línea."; 35: ! El player ha usado un proname, como COMELO, pero el ! parser no tiene asignado un valor a ese proname. "No estoy seguro de a qué se refiere ~", (address) pronoun_word, "~."; 36: ! El player ha puesto una lista de objetos y ha usado la ! palabra EXCEPTO para exceptuar algo que no estaba incluido ! en la lista, por ejemplo: COGE TODAS LAS MONEDAS EXCEPTO EL ! SACO. "Has exceptuado algo que no estaba incluido."; 37:! La gramática de un verbo obliga a que el objeto sobre el que ! se actúe sea animate (tiene un token de tipo "creature"), ! pero el player lo ha intentado sobre un objeto que no es ! animate. "Sólo puedes hacer eso con seres animados."; 38: ! La primera palabra usada por el player es desconocida (o ! la primera palabra tras la comma, si se trata de una orden a ! un PNJ) "No conozco ese verbo."; 39: ! El player intenta actiones sobre las palabras que están en ! la propiedad "irrelevante" de la localidad "Eso no es importante."; 40: ! El player ha usado un proname, como EXAMINALO, pero el ! proname se refiere a un objeto que ya no está visible. "Ahora mismo no puedes ver lo que representa el pronombre ~", (address) pronoun_word, "~ (", (the) pronoun_obj, ")."; 41: ! Este error no sale nunca. Probablemente sigue aqui por ! razones de compatibilidad, o por despiste de Graham ¿Tal vez ! ha sido sustituido en versiones mas recients por el mensaje ! número 28? "No entendí la última parte de la orden."; 42: ! El player ha solicitado un numero de objetos en una lista ! de objetos multiples, pero el parser no es capaz de ! encontrar tantos. Por ejemplo: COGE SEIS MONEDAS. ! En x1 se recibe el número de objetos hallados por el ! parser. if (x1==0) "No hay suficientes."; else if (x1==1){ print "Aquí sólo hay un"; if (multiple_object-->1) print (o) multiple_object-->1; else print "o"; " disponible."; } else "Sólo hay ", (number) x1, " disponibles para esa acción."; 43: ! El player ha puesto TODO como objeto múltiple, pero el ! parser no ha encontrado ningún objeto. En realidad este ! error parece no producirse nunca (second bug de librería) ya ! que el que siempre acaba generándose es el siguiente (44) "¡No encuentro nada para hacer eso!"; 44: ! El player ha intentado objetos múltiples usando TODO ! pero el parser no ha encontrado ninguno. Por ejemplo, COGE ! TODO o DEJA TODO si no hay nada cerca o en el inventario. ! Modificado en [020621] para dar un mensaje más coherente ! si el player tiene algún objeto en su inventario. if (action_to_be == ##Drop) { print "¡Pero si no llevas nada"; if (children (player)) " de eso!"; else "!"; } print "No hay nada para "; LanguageVerb(verb_word); "."; 45:! El player ha nombrado un PNJ ambiguo (hay más de noun con el ! mismo name cerca). El parser le pide aclaración. Este ! mensaje es la primera parte de la pregunta, el resto lo pone ! el parser (que es la lista de PNJs entre los que ! duda). Debemos poner a 1 la variable PreguntaCualExactamente ! cuando se generan este tipo de preguntas aclaratorias. print "¿Quién concretamente, "; PreguntaCualExactamente=1; ImprimirListaDudosos("o"); ! print "?^"; 46:! El player ha nombrado un objeto ambiguo (hay más de noun con el ! mismo name cerca). El parser le pide aclaración. Este ! mensaje es la primera parte de la pregunta, el resto lo pone ! el parser (que es la lista de objetos entre los que ! duda). Debemos poner a 1 la variable PreguntaCualExactamente ! cuando se generan este tipo de preguntas aclaratorias. print "¿Cuál concretamente, "; PreguntaCualExactamente=1; ImprimirListaDudosos("o"); ! print "?^"; 47: ! El player ha respondido "TODOS" o "AMBOS" a una pregunta ! aclaratoria como la anterior, pero el verbo no admite ! objetos múltiples print "Lo siento, sólo puedes referirte a un objeto aquí. ¿Cuál exactamente?^"; PreguntaCualExactamente=1; 48: !El player ha escrito una frase u orden a PSI incompleta, !como BESA (verbo aplicado sobre PSIs normalmente). !El parser le pregunta para que complete la frase PreguntaCualExactamente=1; ! print "Mensaje 48^"; ![infps] debug if (IniciarPregunta()==0) print "A quién"; if (actor ~= player) print " tiene que "; else print " quieres "; IdiomaImprimirComando(); if (actor~=player) print " ", (the) actor; print "?^"; 49: !El player ha escrito una frase u orden incompleta, !como COGE (verbo aplicado sobre objetos normalmente). !El parser le pregunta para que complete la frase PreguntaCualExactamente=1; ! print "Mensaje 49^"; ![infps] debug if (IniciarPregunta()==0) print "Qué"; if (actor ~= player) print " tiene que "; else print " quieres "; IdiomaImprimirComando(); if (actor~=player) print " ", (the) actor; print "?^"; !#IFNDEF NO_PUNTUACION; 50: ! El player acaba de realizar una acción que puntúa (la ! librería ha detectado que la variable score ha cambiado ! de valor). Se informa de ello al player. El parámetro x1 ! contiene el incremento (o decremento) en la puntuación. print "Tu puntuación ha "; if (x1 > 0) print "aumentado"; else { x1 = -x1; print "disminuido"; } print " en ", (number) x1, " punto"; if (x1 > 1) print "s"; !#ENDIF; ! NO_PUNTUACION 51: ! El player ha intentado una acción con objeto múltiple ! (como COGE TODO). Esta acción es convertida por el parser en ! una serie de actiones COGE OBJETO1, COGE OBJETO2, etc... Si ! en la ejecución de alguna de estas actiones encuentra que la ! localidad del player ha cambiado, debe abortar el ! proceso. Este mensaje informa de ello al player. ! "(Ya que ha ocurrido algo dramático, se ha recortado la lista de objetos sobre los que actuabas)"; 52: ! En los menús, se espera a que el player escriba un número ! para mostrar una entrada del menú. Si pulsa un numero ! incorrecto, se saca este mensaje. El parámetro x1 contiene ! el número más alto válido "^Escribe un número del 1 al ", x1, ", 0 para volver a mostrarlo, o pulsa Intro."; 53: ! Mensaje que muestra el sistema de menús cuando espera una ! tecla "^[Por favor, pulsa ESPACIO]"; ! [6/11] agregados: 54: "[Comentario guardado]"; 55: "[Comentario NO guardado]"; 56: print ".^"; 57: print "?^"; } No,Yes: "Sólo era una pregunta retórica."; ! Cuando el jugador pone SI o NO, a secas, se genera esta ! acción. Está pensado por si el juego suelta una frase del estilo ! de "¿Pero tú eres tonto?" y el jugador responde NO. ! De todas formas, hay un problema, y es que NO es normalmente la ! acción Ir al noroeste. Si queremos que NO sea provisionalmente ! la acción No, entonces el juego debe poner un 1 en la variable ! PreguntaSiNo, antes de escribir el texto "¿Pero tú eres tonto?". ! En este caso, el parser interpretará "NO" como la acción No, ! pero sólo en el siguiente turno. Después recuperará su antiguo ! significado de Ir al Noroeste. NotifyOff: "Notificación de puntuación desactivada."; Objects: ! Ante el verbo "OBJETOS" se genera esta acción, que muestra una ! lista de todos los objetos que el jugador ha manipulado a lo ! largo del juego, junto con una indicación de qué hizo con ellos. ! ! 1: Texto introductorio a la lista ! 2: Si no ha manejado aún ninguno ! 3: indicación de que lo lleva puesto ! 4: indicación de que lo lleva en su inventario ! 5: indicación de quién lo tiene ahora (si lo tiene un PNJ) ! 6: indicación de dónde está el objeto (si está en una localidad) ! 7: indicación de dónde está el objeto (si está en un "entrable") ! 8: indicación de dónde está el objeto (si está en un recipiente) ! 9: indicación de dónde está el objeto (si está en un soporte) ! 10: indicación de que se ha perdido (no está en ninguno de los ! casos anteriores) switch(n) { 1: "Objetos que has manejado:^"; 2: "Ninguno."; ! 3: print " (puest", (o) noun, ")"; 3: print " (puesto)"; ! [infsp] fixed, no se pasa el objeto ! 4: print " (l", (o) noun, " llevas)"; 4: print " (contigo)"; ! [infsp] fixed ! 5: print " (en poder ", (del) noun, ")"; !siendo x1 el animate que lo tiene 5: print " (dejado con alguien)";! [infsp] fixed 6: print " (ahora en ", (name) x1, ")"; 7: print " (ahora en ", (the) x1, ")"; 8: print " (ahora dentro ", (del) x1, ")"; 9: print " (ahora en ", (the) x1, ")"; ! 10: print " (perdid", (o) x1, ")"; 10: print " (perdido)"; ! [infsp] fixed } Open: ! 1: Error, el objeto no tiene el atributo "abrible" ! 2: Error, el objeto es abrible, pero tiene "cerrojoechado" ! 3: Error, el objeto es abrible, pero ya tiene el atributo ! "abierto" ! 4: Exito, el objeto se abre, y además era recipiente y tenía ! cosas dentro. Se muestra entoces la lista de objetos que ! había en su interior (si habia algo) ! 5: Exito, el objeto se abre (pero no tiene nada en su ! interior, o no era recipiente). switch(n) { 1: print_ret "No es algo que pueda abrirse."; 2: "Está", (n) x1, " cerrad", (o) x1, " con llave."; 3: "Ya estaba", (n) x1, " abiert", (o) x1, "."; 4: print "Abres ", (the) x1, ", descubriendo "; if (WriteListFrom(child(x1), ENGLISH_BIT + TERSE_BIT + CONCEAL_BIT)==0) "nada."; "."; 5: "Abres ", (the) x1, "."; } Order: print_ret (The) x1, " tiene", (n) x1, " mejores cosas que hacer."; Places: ! El verbo "LUGARES" muestra un listado de los lugares que el ! jugador ha visitado. Aquí debemos escribir el texto ! introductorio a esa lista. switch (n) { 1: print "Has visitado: "; 2: print ".^"; } Pray: "No obtienes nada práctico de tus oraciones."; Prompt: print "^>"; ! El prompt aparece justo antes de pedir una nueva línea al ! jugador. Puede definirse para que sea una frase, o se genere una ! frase aleatoria en cada turno. Pronouns: ! Esta acción (generada por el verbo PRONOMBRES) muestra una lista ! de qué significa en ese momento para el parser cada proname ! -lo, -la, -los, -las... ! ! 1: Texto introductorio ! 2: La palabra "es" ! 3: texto a mostrar si el proname no está definido ! 4: Si el juego no define pronames ! 5: [6/11] switch(n) { 1: print "En este momento, "; 2: print "es "; 3: print "no está definido"; 4: "el juego no conoce ningún pronombre."; 5: "."; } Pull, Push, Turn: ! Las acciones Tirar, Empujar y Girar generan todas ellas los ! mismos mensajes, pero pueden darse 4 casos: ! 1: Que el objeto tenga el atributo 'estatico' ! 2: Que el objeto tenga el atributo 'escenario' ! 3: El objeto no tiene 'estatico' ni 'escenario' ! 4: El objeto es un ser animado ! [Nota, si el objeto tiene ambos 'estatico' y 'escenario' se ! está también en el caso 1] switch(n) { 1: "Está", (n)x1, " firmemente sujet", (o)x1, "."; 2: "No eres capaz."; 3: "No ocurre nada, aparentemente."; 4: "Eso sería, como poco, maleducado."; } ! Push: see Pull PushDir: ! La acción EmpujarDir se genera ante frases como EMPUJA EL COCHE ! HACIA EL NORTE. Hay 3 casos posibles: ! 1: Si el juego no ha previsto la posibilidad de empujar ese ! objeto hacia una dirección (o sea, no llama a la rutina ! PermitirEmujarDir). Esta es la respuesta por defecto más ! habitual. ! 2: Si el jugador pone tras HACIA algo que no es una dirección. ! (respuesta por defecto en este caso) ! 3: Si intenta empujar hacia arriba o hacia abajo switch(n) { 1: "No creo que empujar ", (the) x1, " sirva para nada."; 2: "Eso no es una dirección."; 3: "No, no puedes en esa dirección."; } PutOn: ! 1: Error, el objeto no está en poder del jugador. [Nota, ! conviene mirar en este caso si el objeto es animado o no, ! para generar un mensaje más adecuado] ! 2: Error, el jugador intenta poner un objeto sobre sí mismo ! 3: Error, el jugador intenta poner el objeto sobre otro que no ! tiene el atributo "soporte" ! 4: Error, el jugador intenta poner un objeto sobre el propio ! jugador. ! 5: Aviso, el objeto es una prenda puesta. La librería va a ! quitárselo automáticamente antes de reintentar la acción ! PonerSobre ! 6: Error, se intenta poner el objeto sobre otro en el que ya no ! queda sitio (el número de objetos que caben en el soporte se ! indica en su propiedad "capacidad") ! 7: Exito. Mensaje a mostrar para cada objeto puesto cuando se ! ponen muchos (ej: PON TODO SOBRE LA MESA) ! 8: Exito. Mensaje a mostrar cuando se pone un solo objeto sobre ! otro. switch(n) { 1: if (x1 has animate) "Antes tendrías que", (coge) "rl", (o) x1, ", y no sé si se dejará", (n) x1, "."; else "Necesitas tener ", (the) x1, " para poder poner", (lo) x1, " donde sea."; 2: "No puedes poner un objeto sobre sí mismo."; 3: "Poner cosas sobre ", (the) x1, " no servirá de nada."; 4: "Te falta destreza."; 5: "(primero te ", (lo) x1, " quitas)^"; 6: "No queda sitio en ", (the) x1, " para poner nada más."; 7: "Hecho."; 8: "Colocas ", (the) x1, " sobre ", (the) second, "."; } Quit: ! 1: Respuesta al comando FIN ! 2: Respuesta si el jugador escribe algo distinto de "si" o "no" switch(n) { 1: print "Por favor, responde sí o no."; 2: print "¿Realmente quieres abandonar el juego? "; ! ELIUK BLAU: antes "Seguro que..." } Remove: ! 2 mensajes de error y 1 de exito ! 1: El recipiente que contiene el objeto que el jugador quiere ! sacar, está cerrado. (ml_o apunta al objeto, no al ! recipiente, el cual puede obtenerse con parent(ml_o)) ! 2: El objeto no está dentro del recipiente que el jugador ha ! dicho. ! 3: Exito switch(n) { 1: "Por desgracia ", (the) parent(x1), " ",(esta) parent(x1), " cerrad", (o) parent(x1), "."; 2: if (second has animate) "¡Pero si no ", (lo) x1, " tiene", (n) second, "!"; "¡Pero si no ", (esta) x1, " ahí ahora!"; 3: if (verb_word=='quita') "Quitad", (o)x1, "."; "Sacad", (o) x1, "."; } Restart: ! 1: Respuesta al comando REINICIAR ! 2: Si no se puede reiniciar switch(n) { 1: print "¿Realmente quieres reiniciar el juego? "; ! ELIUK BLAU: antes "Seguro que..." 2: "Error."; } Restore: ! 1: Si no se pudo cargar la partida con LOAD ! 2: Exito (no llega a mostrarse, porque en caso de éxito el ! estado del juego cambia al momento en que se salvó. El "Ok" ! que se ve entonces es el del comando Salvar. switch(n) { 1: "Error. No se pudo recuperar la partida."; 2: "Ok."; } Rub: "Ya ", (esta) x1, " bastante limpi", (o) x1, "."; Save: ! 1: Si no se pudo guardar el juego ! 2: Éxito switch(n) { 1: "Error. No se pudo guardar."; 2: "Ok."; } ! Puntuación del juego. Puede activarse porque el player lo pide ! (con el verbo "PUNTUACION") o porque el juego ha terminado. En ! este ultimo caso, la variable "deadflag" valdrá true. ! [6/11] agregado de (2) Score: switch (n) { 1: if (deadflag) print "En este juego, tu puntuación ha sido "; else print "Hasta el momento tu puntuación es "; print score, " de un total de ", MAX_SCORE, ", en ", turns, " turno"; if (turns>1) print "s"; return; 2: "Este juego no tiene conteo de puntuación."; } ScriptOff: ! 1: Error ya estaba desactivada la transcrcipción ! 2: Exito switch(n) { 1: "La transcripción ya estaba desactivada."; 2: "^Fin de la transcripción."; 3: "Intento fallido de finalización de transcripción."; } ScriptOn: ! 1: Error, ya estaba activada la transcrcipción ! 2: Éxito (parte inicial del mensaje, la librería añade el título ! del juego obtenido de la constante Historia) switch(n) { 1: "La transcripción ya estaba activada."; 2: "Iniciando la transcripción de "; 3: "Intento fallido de comienzo de transcripción."; } Search: ! La acción BuscarEn se genera ante la frase MIRA EN RECIPIENTE, ! MIRA EN SOPORTE, REGISTRA OBJETO. ! ! 1: Error, estamos a oscuras. ! 2: Éxito examinando soporte, pero no hay nada sobre él. ! 3: Éxito examinando soporte, listar lo que hay. ! 4: El objeto examinado no es soporte ni recipiente, mensaje ! estándar indicando que no se encuentra nada. ! 5: Error, El objeto examinado es recipiente, pero está cerrado. ! 6: Éxito, el objeto examinado es recipiente abierto, pero no ! tiene nada dentro. ! 7: Éxito, el objeto examinado es recipiente abierto y tiene ! cosas dentro. Listarlas. switch(n) { 1: "Está muy oscuro."; 2: "No hay nada sobre ", (the) x1, "."; 3: print "Sobre ", (the) x1; WriteListFrom(child(x1), TERSE_BIT + ENGLISH_BIT + ISARE_BIT + CONCEAL_BIT); "."; 4: "No encuentras nada interesante."; 5: "No puedes ver lo que hay dentro ", (del) x1, " porque ", (esta) x1, " cerrad", (o)x1, "."; 6: print_ret (The) x1, " ", (esta) x1, " vací", (o)x1,"."; 7: print "En ", (the) x1; WriteListFrom(child(x1), TERSE_BIT + ENGLISH_BIT + ISARE_BIT + CONCEAL_BIT); "."; } Set: "No, no puedes."; ! Fijar sale ante la frase FIJA OBJETO o AJUSTA OBJETO SetTo: "Eso no puede regularse a ningún valor."; ! PonerA sale ante la frase AJUSTA DIAL A 23 o FIJA CONTROL EN ! ACTIVADO, o PON REGULADOR A 30 Show: ! 1: Error, el jugador intenta mostrar un objeto que no tiene. ! 2: Aviso, se ha enviado la acción Mostrar al PNJ, pero este no ! ha respondido. En este caso ml_n apunta al PNJ y no al objeto ! que le hemos mostrado. switch(n) { 1: "No tienes ", (the)x1, "."; 2: print_ret (The) x1, " no muestra", (n) x1, " interés."; } Sing: "Cantas fatal."; Sleep: "No estás especialmente somnolient", (o) player, "."; Smell: "No hueles nada extraño."; Sorry: "Oh, no es necesario que te disculpes."; ! Esta acción se genera si el jugador pone "LO SIENTO", ! "PERDONA" o cosas similares. Squeeze: ! Dos casos: ! 1: Tratar de retorcer un ser animado ! 2: Cualquier otro objeto switch(n) { 1: "¡Las manos quietas!"; 2: "No consigues nada haciendo eso."; } Strong: "Los verdaderos aventureros no usan ese vocabulario."; ! Y esta si usa como primera palabra (verbo) un taco. Swim: "No hay agua suficiente en la que nadar."; Swing: "No es adecuad", (o) x1, " para columpiarse."; SwitchOff: ! 1: Error, el objeto no tiene el atributo "conmutable" ! 2: Error, el objeto ya tenia desactivado el atributo ! "encendido" ! 3: Exito, el objeto tiene ahora desactivado "encendido" switch(n) { 1: print_ret "No es algo que pueda apagarse."; 2: print_ret "Ya estaba", (n) x1, " apagad", (o) x1, "."; 3: "Apagas ", (the) x1, "."; } SwitchOn: ! Generada al intentar ENCIENDE OBJETO si el objeto tiene el ! atributo "conmutable". Observar que si no lo tiene, la acción ! que se genera será sin embargo Quemar. ! ! 1: Error, el objeto no es conmutable (este error no aparecerá ! si el jugador pone ENCIENDE OBJETO, ya que en este caso la ! acción generada será Quemar objeto, pero puede aparecer si ! pone CONECTA OBJETO) ! 2: Error, el objeto ya tenía el atributo "encendido" ! 3: Exito, el objeto tiene ahora activado "encendido". switch(n) { 1: print_ret "No es algo que pueda encenderse."; 2: print_ret "Ya estaba", (n) x1, " encendid", (o) x1, "."; 3: "Enciendes ", (the) x1, "."; } Take: ! Hay 13 casos diferentes. Se trata de 1 mensaje de éxito y 11 ! mensajes de error y un aviso ! 1: Exito ! 2: Error, el objeto cogido es el propio jugador ! 3: Error, el objeto cogido es animado ! 4: Error, el jugador está subido o metido en el objeto que ! intenta coger ! 5: Error, el jugador ya tenía ese objeto ! 6: Error, el objeto está en poder de un ser animado [ml_o ! apunta al ser, no al objeto, el cual puede obtenerse en la ! variable "uno"] ! 7: Error, el objeto es un sub-objeto de otro (está dentro de un ! objeto que tiene el atributo "transparente", pero no tiene el ! atributo "recipiente" ni "soporte") ! 8: Error, el objeto está dentro de otro, pero este otro no es ! recipiente ni soporte ni transparente (probablemente un error ! de programación) ! 9: Error, el objeto está dentro de un recipiente cerrado. ! 10: Error, el objeto es escenario ! 11: Error, el objeto es estatico (no puede ser llevado de la ! localidad en que se halla) ! 12: Error, el jugador lleva demasiados objetos ! 13: Mensaje de aviso, la librería ha decidido mover objetos del ! inventario al "objeto saco" para hacer sitio y que el jugador ! pueda coger el objeto. [El objeto saco es uno que puede ! declarar el programador. Si el jugador lo coge y lo lleva ! consigo, la librería lo usará automáticamente como mochila ! para descargar al jugador cuando sea necesario] switch(n) { ! 1: "Hecho."; ! [infsp] fixed, no se pasa el objeto 1: if (dialecto_sudamericano) print "Tomad"; else print "Cogid"; print_ret (o) noun, "."; 2: "Siempre te tienes a ti mism", (o) player, "."; 3: "No creo que ", (al) x1, " le", (s) x1, " gustara."; 4: print "Tienes que "; if (x1 has supporter) print "bajarte "; else print "salirte "; print_ret (del) x1, " antes."; 5: "Ya tienes ", (the) x1, "."; 6: "Parece que pertenece", (n) noun, " ", (al) x1, "."; 7: "Parece", (n) noun, " formar parte ", (del) x1, "."; 8: "No ", (esta) x1, " disponible", (s)x1, "."; 9: print_ret (The) x1, " no ", (esta) x1, " abiert", (o) x1, "."; 10: "Difícilmente podrías llevarte eso."; 11: print_ret (The) x1, " está fij", (o) x1, " en el sitio."; 12: "Ya llevas demasiadas cosas."; 13: "(colocas ", (the) x1, " en ", (the) SACK_OBJECT, " para hacer sitio)"; } Taste: "No saboreas nada inesperado."; Tell: ! Dos casos: ! 1: El jugador habla consigo mismo ! 2: Hablar con cualquier otro ser animado ! [Nota: Hablar con un objeto inanimado no está permitido por el ! parser, que da un error y no llega a generar la acción] ! [Los errores de parser se tratan en la sección "Miscelanea" de ! esta rutina, al final] switch(n) { 1: "Hablas sol", (o) player, " durante un rato."; 2: "No has provocado ninguna reacción."; } Think: "Vaya. Qué buena idea."; ThrowAt: ! Dos casos: ! 1: Lanzar cosas a objetos inanimados ! 2: Lanzar cosas a objetos animados switch(n) { 1: "No serviría de nada."; 2: "En el último momento te echas atrás."; } ! Tie: see JumpOver. Touch: ! Tocar genera tres mensajes diferentes ! 1: Si se intenta tocar a un ser animado ! 2: Tocar un objeto normal del juego ! 3: Tocarse a si mismo switch(n) { 1: "¡Las manos quietas!"; 2: "No notas nada extraño al tacto."; 3: "Si crees que eso servirá de algo..."; } ! Turn: see Pull. Unlock: ! QuitarCerrojo se genera ante ABRE CON , o también ! ante QUITA CERROJO A (en este segundo caso no se ! especifica la "llave" que abre la puerta). ! ! 1: Error, el objeto que se intenta abrir, no tiene el atributo ! cerrojo. ! 2: Error, el objeto que se intenta abrir tiene atributo ! "cerrojo", pero no tiene atributo "cerrojoechado" ! 3: Error, el que se intenta usar como llave, no ! coincide con la propiedad "con_llave" del que ! intenta ser abierto. ! 4: Exito. El se abre (con si éste ha sido ! especificado, el cual podemos encontrarlo en la variable "otro" switch(n) { 1: "No parece", (n) x1," tener ningún tipo de cerrojo."; 2: print_ret (The) x1, " ya tenía", (n) x1, " abierto el cerrojo."; 3: if (second) "No parece", (n) x1, " encajar en la cerradura."; "Necesitas algún tipo de llave."; 4: if (second) "Quitas el cerrojo ", (al) x1, " con ", (the) second, "."; "Quitas el cerrojo ", (al) x1, "."; } VagueGo: ! El jugador ha dicho IR sin especificar a dónde "Tienes que especificar en qué dirección ir."; Verify: ! 1: Éxito ! 2: Error en la verificación switch(n) { 1: "Fichero de juego verificado e intacto."; 2: "El fichero de juego no parece intacto, puede estar corrompido (a menos que estés jugando con un intérprete muy primitivo que no sea capaz de realizar la comprobación)."; } Wait: "Pasa el tiempo..."; Wake: "La cruda realidad es que esto no es un sueño."; WakeOther: "No parece necesario hacer eso."; Wave: ! Agitar genera dos mensajes diferentes: ! 1: Si se intenta agitar un objeto que no está en el inventario ! 2: Si se agita un objeto que sí está en el inventario switch (n) { 1: "No l",(o) x1, " tienes."; 2: "Te sientes ridícul", (o) player, " agitando ", (the) x1, "."; } WaveHands: "Te ves ridícul", (o) player, " gesticulando así."; ! La acción Gesticular sale ante las frases "gesticula", "agita la ! mano", "sacude la mano", "saluda con la mano"... Wear: ! 1: Error, el objeto no tiene el atributo "prenda" ! 2: Error, el jugador no tiene el objeto ! 3: Error, el objeto ya tiene el atributo "puesto" ! 4: Exito. switch(n) { 1: "¡No puedes ponerte eso!"; 2: "No ", (lo) x1, " tienes."; 3: "¡Ya ", (lo) x1, " llevas puest", (o) x1, "!."; 4: "Te pones ", (the) x1, "."; } ! Yes: see No. ]; #endif; ! SIN_MENSAJES !------------------------------------------------------------------------------- ! FIN: Seccion Mensajes !=============================================================================== ! --------------------------------------------------------------------------- ! Otras rutinas de soporte para el AUTOR de Aventuras [ TextoLlamativo txt; ! Imprime un texto rodeado de asteriscos y en negrita. ! Puedes cambiarlo si quieres que aparezcan en otros formatos. #ifdef TARGET_ZCODE; #IFV5; style bold; #ENDIF; #ifnot; ! TARGET_GLULX glk($0086, 5); ! set alert style #endif; ! TARGET_ ! print "***", (string) txt, "***"; ! [010508] Corregido bug (string) print (string) txt; ! infsp fix, los asteriscos ya se ponian en parserm.h #ifdef TARGET_ZCODE; #IFV5; style roman; #ENDIF; #ifnot; ! TARGET_GLULX glk($0086, 0); ! set normal style #endif; ! TARGET_ ]; ! La siguiente función imprime la lista de objetos entre los que el ! parser tiene dudas (porque todos ellos responden al name que ha ! usado el player). Esta rutina es llamada desde los mensajes ! (Miscellany,45) y (Miscellany,46) ! Modificada en [021025] para que pregunte sólo por aquellos objetos ! empatados a puntuación máxima por la desambiaguación. [ ImprimirListaDudosos2 conjuncion i k marker punt_max num_objs; marker = 0; ! obtener puntuacion maxima y cuantos objetos la tienen for (i = 0, punt_max = -1: i < number_matched: i++) { if (match_scores-->i > punt_max) { punt_max = match_scores-->i; num_objs = 1; } else if (match_scores-->i == punt_max) num_objs++; } for (i = 1: i <= number_of_classes: i++) { while (((match_classes-->marker) ~= i) && ((match_classes-->marker) ~= -i)) marker++; k=match_list-->marker; if (match_scores-->marker == punt_max) { if (match_classes-->marker > 0) print (the) k; else print (a) k; if (i < num_objs - 1) print ", "; ! imprimir separadores if (i == num_objs - 1) print " ", (string) conjuncion, " ";!imprimir ultimo separador } } ]; [ ImprimirListaDudosos conjuncion i ii k marker punt_max num_objs chk_class; marker = 0; for (i = 0, punt_max = -1: i < number_matched: i++) { if (match_scores-->i > punt_max) { punt_max = match_scores-->i; num_objs = 1; } else if (match_scores-->i == punt_max) num_objs++; } chk_class = false; if (num_objs >= number_of_classes) { num_objs = number_of_classes; chk_class=true; } for (i = 1, ii = 0 : i <= number_of_classes: i++) { while (((match_classes-->marker) ~= i) && ((match_classes-->marker) ~= -i)) marker++; k=match_list-->marker; if ((match_scores-->marker == punt_max) || (chk_class == true)) { ii++; if (match_classes-->marker > 0) print (the) k; else print (a) k; if (ii < num_objs - 1) print ", "; if (ii == num_objs - 1) print " ", (string) conjuncion, " "; } } ]; ! ============================================================================== Constant LIBRARY_SPANISH; ! for dependency checking. ! ==============================================================================