61 7: CONTROL DE ESTRUCTURAS GOTO (salta a un nuevo numero de linea) La accion de GOTO transfiere el control del programa de un lugar a otro. Existen 3 formas de presentacion de este comando en AMOS: 1) GOTO label "label" es un marcador de lugar opcional al lado de una linea. Los nombres de etiqueta (label) se definen usando los dos puntos ":" como sigue: label: La etiqueta puede consistir en cualquier cadena de caracteres al- fanumericos, incluyendo "-". Se construye utilizando las mismas reglas que se aplican a los tipos de variables y procedimientos. 2) GOTO line number Cualquier linea de AMOS Basic puede ser opcionalmente precedi- da de un numero. Esos numeros de linea se incluyen exclusivamente para compatibilidad con otras opciones Basic (como STOS en el Ata ri ST). Es preferible utilizar etiquetas, ya que son mucho mas fa cilmente legibles y recordables. 3) GOTO variable La variable puede ser cualquier expresion permitida en AMOS Ba sic. Esta expresion debe ser un numero entero o una cadena. Los enteros ejecutan un numero de linea para el GOTO, mientras que las cadenas retienen el nombre de una etiqueta. En terminos tecnicos, esta construccion es conocida como un GOTO Computerizado. Generalmente es usado por programadores exper tos, pero es increiblemente util en ciertas ocasiones. Por ejem- plo: Room=3 Begin: Goto "room"=Str$(Room)-" " End Room3: Print"room three!" Goto Begin 62 GOSUB (Salta a una subrutina) GOSUB es otra instruccion anticuada, que te permite la posibili- dad de continuar un programa en otro mas pequeño, mas manejable y que se conocen como SUBRUTINAS. Actualmente GOSUB has sido casi desplazado por completo por el sistema de PROCEDIMIENTOS de AMOS Basic. Sin embargo, GOSUB es util cuando se trata de traducir pro gramas de otras versiones de Basic como es el STOS. Al igual que GOTO existen 3 formas distintas de GOSUB: 1) GOSUB n (salta a una subrutina en la linea n) 2) GOSUB name (salta a una etiqueta AMOS) 3) GOSUB exp (salta a una etiqueta o una linea dependiendo de la expresion exp) Ejemplo: For i=1 to 10 Gosub TEST Next I Direct Test: Print"This is an example of GOSUB":Print "I equals ";i Return: Rem salida de la subrutina TEST y regreso al programa Es una buena costumbre el emplazar todas las subrutinas al final del programa principal, lo que facilita el listado del mismo. Tam bien puedes añadir una orden EDIT o DIRECT al final de tu progra- ma principal, al objeto de evitar que AMOS ejecute tus subrutinas despues de que el programa haya terminado, generando por tanto un mensaje de error. RETURN (Regreso de una subrutina) RETURN sale de una subrutina a la que previamente se ha accedido mediane un GOSUB. Advierte que una simple instruccion GOSUB puede contener varios RETURN. Por lo que puedes salir de la subrutina a traves de varias vias dependiendo de la situacion. POP (Sustituye al comando RETURN despues de un GOSUB) Normalmente es ilicito salir de un comando GOSUB usando un GOTO standard. Esto sin embargo, puede ser un inconveniente, especial- mente si se produjera un error, por lo que es inaceptable que tu intentes regresar al programa principal en el mismo punto de par- tida. La instruccion POP sustituye al comando RETURN generado por un GOSUB, y te permite dejar la subrutina en cualquier momento que desees, sin tener que ejecutar primero el comando RETURN. Ejemplo 63 Do Gosub TEST Loop Bye: Print "Popped out" Direct: TEST: Print "Hi there!" If mouse key then pop: goto Bye Return IF ... THEN ... ¡ELSE¿ (elige entre acciones alternativas) La instruccion IF...THEN te permite emplazar una decision simple dentro de un programa Basic. El formato es If condition THEN suceso 1 ¡Else suceso 2¿ "condition" puede un listado de condiciones incluyendo AND y OR. Los sucesos 1 y 2 pueden ser tambien un listado de instrucciones de AMOS Basic. Si deseas saltar a un numero de linea o a una eti- queta, tendras que incluir un comando GOTO de forma separada como sigue: If TEST then GOTO label: This is fine Pero si por olvido, omites GOTO, obtendras un mensaje de error "procedure not defined". If TEST then LABEL: Rem esto hace llamada a un procedimiento El alcance de esta instruccion IF...THEN esta limitada a una simple linea de tu programa en Basic. Ademas, este comando ha si- do superado ampliamente por el mucho mas poderoso comando IF... ELSE...ENDIF. IF ... ¡ELSE¿ ... ENDIF (Es un test estructurado) Pese a que la original forma de IF...THEN es indudablemente util, realmente esta pasada de moda si la comparamos con las facilida- des encontradas en la moderna version Basic de AMOS. Este comando te permite ejecutar completos listados de instrucciones dependien do del resultado de un test simple. If test =TRUE << lista de instrucciones >> Else << lista de instrucciones 2 >> Endif 64 NOTA: es ilegal usar un IF...THEN normal dentro de un test estruc turado. Este debera ser reemplazado por su instruccion equivalen- te IF...ENDIF. Asi: If TEST then goto LABEL else LABEL2 Pasara a ser: If TEST: Goto LABEL: Else goto LABEL2: Endif O bien: If TEST Goto LABEL Endif He aqui un ejemplo de la instruccion IF...ENDIF en accion: Input "Introduce valores para a,b y c";A,B,C If A=B Print "Igual" Else Print "Diferencia "; If A<>B and A<>C Print ", y C no es tampoco la misma!" Endif Enf if Cada orden IF en tu programa debe ir aparejada con una instruc- cion simple ENDIF, que informara a AMOS con precision que grupo de instrucciones deben ser ejecutadas en tu test. Ten en cuenta que THEN no se utiliza en este tipo de instruccio- nes. Esto puede crearte algun problema si estas demasiado acostum brado a las viejas versiones Basic de Commodore. FOR ... NEXT (repite una parte del programa un numero espe- cifico de veces) FOR indez=first TO last ¡STEP inc¿ < lista de instrucciones > NEXT ¡index¿ "INDEX" se trata de un contador que sera incrementado despues de cada una de las vueltas. Al comienzo del ciclo, este contador debe cargarse con el resultado de la expresion "first". Las ins- trucciones entre FOR y NEXT se ejecutaran hasta alcanzar la or- den NEXT. "INC" es un valor que se añadira al contador despues de cada vuelta por la instruccion NEXT. Si se omitiera este valor, se añadiria automaticamente la unidad. Ten en cuenta que si INC es negativo, el ciclo se interrumpi- ra cuando el contador sea menor que el valor "first". De este modo todo el ciclo sera ejecutado al reves. 65 Una vez dentro del ciclo, "INDEX" puede ser leido desde tu programa como una variable normal. Pero no podras cambiar su va- lor de ninguna forma, a menos que quieras obtener un mensaje de error. Por cada orden FOR en tu programa, debe existir una instruc- cion simple NEXT. Tambien podras utilizar las formas abreviadas usadas en otros Basic como NEXT R,T. A continuacion un par de ejemplos de estos ciclos: For I=32 to 255 : Print CHR$(i);:Next i For R1=20to100 step 20 For R2=20to100 step 20 For A=0 to 3 Ink A Ellipse 160,100,R1,R2 Next A Next R2 Next R1 WHILE ... WEND (Repite una parte del programa mientras se mantenga una condicion como cierta) WHILE condition < lista de instrucciones > WEND "Condition" puede ser cualquier tipo de test que desees cons- truir, incluyendo si fuera necesario las instrucciones logicas. Se realiza un chequeo en cada vuelta del ciclo. Si el resultado del test fuera -1 (cierto), entonces se ejecutarian las instruc- ciones entre WHILE y WEND, de otro modo el ciclo se interrumpiria y AMOS continuara con la siguiente instruccion. Ejemplo: Input "Teclea un numero";X Print "Contando hasta 11" WHILE X < 11 Inc X Print X WEND Print "Ciclo terminado" El numero de veces que WHILE ejecuta este programa dependera del valor que introduzcas en la rutina. Si introduces un numero mayor de 11, el ciclo no se ejecutara jamas. WHILE solo ejecutara ins- trucciones si la condicion es cierta al principio del programa. 66 REPEAT ... UNTIL (Repite hasta que se satisfaga una condi- cion) REPEAT < lista de instrucciones > UNTIL condicion REPEAT ... UNTIL es muy similar a WHILE ... WEND, excepto que la cumplimentacion del test se realiza al final del ciclo en vez de al principio (como pasaba en el anterior). El ciclo se repetira continuamente hasta la condicion especificada sea FALSA. Asi se realizara como minimo UNA VEZ en tu programa. Ejemplo: Repeat Print "AMOS Basic" Until Mouse Key <> 0 DO ... LOOP (Cicla infinitamente) Do < lista de instrucciones > Loop El comando DO ... LOOP toma una lista de instrucciones Basic y las ejecuta, repitiendolas continuamente. Al objeto de poder sa- lir de este bucle, necesitaras utilizar una instruccion especial del tipo EXIT o EXIT IF. La ventaja de este sistema es que se trata de una estructura alternativa al bucle clasico GOTO que aparecia en las primeras versiones Basic. Observa el siguiente ejemplo: TEST: Input "Otro juego S/N"; AN$ If Upper$(AN$)="N" then goto BYE GAME: Rem salta al inicio del juego Goto TEST BYE: Y a continuacion una segunda version, utilizando DO ... LOOP: DO Input "Otro juego S/N";AN$ Exit if upper$ (AN$)="N" GAME: salta al inicio del juego Loop End 67 EXIT (Sale de un bucle DO ... LOOP) EXIT ¡n¿ El comando EXIT sale inmediatamente de uno o mas de un bucle creado con las siguientes instrucciones: - FOR ... NEXT - REPEAT ... UNTIL - WHILE ... WEND - DO ... LOOP Tu programa AMOS saltara entonces automaticamente a la siguien te instruccion tras el bucle en cuestion. "N" es el numero de ciclos que tu deseas dejar. Si este dato fuera omitido, solo se ejecutara el bucle mas interno. EXIT IF (sale de un bucle dependiendo de un test) EXIT IF expresion ¡,n¿ La "expresion" consiste en una serie de test en el formato es tandard de AMOS. Solo se ejecutara la orden de salida si el resul tado del test fuera -1. El parametro "N" funciona de la misma for ma que en el comando anterior. EDIT (Detiene la ejecucion del programa y regresa al editor) La orden EDIT detiene el programa actual y regresa al editor Basic de AMOS. Esto puede ser muy util cuando estes depurando al- guno de tus programas. DIRECT (Sale al modo directo) Termina el programa y salta inmediatamente a modo directo, con lo que puedes examinar el contenido de las variables o realizar un listado del programa en impresora. END (Sale de un programa) Esta instruccion sale de un programa. En este momento se te ofrecera la posibilidad de regresar al editor o al modo directo. ON ... PROC (Salta a uno o varios procedimientos en funcion de la variable) ON v Proc proc1, proc2, proc3,... procN Salta a un procedimiento en funcion de la variable "v". Ten en cuenta que ninguno de los procedimientos que uses con este coman- do podra incluir parametros. Si necesitas transferir informacion a uno de estos procedimientos, deberas colocarla dentro de una variable global. Ver PROCEDIMIENTOS para una mejor aclaracion de esta tecnica. 68 El comando ON ... PROC, es en realidad equivalente a: If v=1 then Proc1 If v=2 then Proc2 : : If v=n then ProcN ON ... GOTO (Salta a una linea en funcion de la variable) ON v GOTO line1, line2, line3, .... lineN La instruccion ON GOTO te permite saltar a un numero determinado de linea dependiendo del resultado de la variable v. Es el equi- valente a las siguientes lineas: If v=1 then Goto Line1 If v=2 then Goto Line2 : : If v=n then Goto LineN ON ... GOSUB (Salta a una rutina en funcion de la variable) ON v GOSUB line1, line2..... Es identica a la anterior, salvo que usa un GOSUB en lugar de un GOTO. EVERY n GOSUB (Llama a una rutina en intervalos regulares) Every n GOSUB Label La orden ON EVERY llama a una rutina en intervalos regulares sin interferir el normal desarrollo del programa principal. Siendo N la longitud del intervalo en cincuentavos de segundo. El tiempo que requiere la rutina para ejecutarse debe ser siempre menor que este intervalo, o en caso contrario aparecera un mensaje de error Despues que se haya accedido a una subrutina, el sistema queda automaticamente anulado. Al objeto de realizar esta llamada de forma continuada, necesitaras añadir el comando EVERY ON antes del RETURN final. Ejemplo: Every 50 Gosub TEST DO Print "Bucle principal" Loop Test: Inc I: Print " Esta es la llamada numero ";i Every On: Return 69 EVERY N PROC (Llama a un procedimiento en intervalos regulares) EVERY n PROC name. EVERY PROC ejecuta automaticamente el procedimiento deseado en intervalos regulares utilizando un potente sistema de interrup- ciones. "N" es el retraso entre cada llamada al procedimiento y se mide en unidades de cincuentavo de segundo. Como en el caso anterior, la interrupcion debe ser activada antes de abandonar el procedimiento, de otra forma la rutina solo sera llamada una sola vez. Asi que necesitas usar la instruccion EVERY ON antes de volver al programa principal con la orden END PROC. Ejemplo: Every 50 Proc Test Do Print "Main loop" Loop Procedure Test Shared I Inc I: Print "Esta es la llamada numero "; I Every On End Proc EVERY ON/OFF (alterna automaticamente las llamadas al procedimiento) EVERY ON/OFF EVERY ON reinicializa el sistema de interrupciones usado por el comando EVERY. Debe ser ejecutado justo antes de finalizar la eje cucion del procedimiento o de la subrutina. EVERY OFF anula las llamadas por completo. Se ejecuta automatica- mente al inicio de uno de esos procedimientos. BREAK ON/OFF (activa o desactiva la tecla CTRL+C Break) BREAK ON/OFF Normalmente puedes interrumpir un programa para regresar al Basic siempre que aprietas CTRL+C. Esta funcion puede ser desactivada usando el comando BREAK OFF. Posteriormente puedes usarla de nue- vo mediante el comando BREAK ON. 70 Manejo de errores ================= ON ERROR GOTO (Capta un error dentro de un programa Basic) ON ERROR GOTO Label Este comando te permite detectar y corregir los errores de un programa Basic AMOS, sin tener que volver a la ventana de edicion A veces, los errores pueden aparecer dentro de un programa sin que sean facilmente predictibles por adelantado. Por ejemplo, el siguiente ejemplo puede ser una buena ilustracion: Do Input "Introduce 2 numeros"; A,B Print A; "dividido por ";B;" es "; A/B Loop Este programa funcionara correctamente hasta que introduzcas un 0 en lugar de B. Entonces podras evitar la aparicion de un mensa- je de error (Division por cero) mediante la instruccion ON ERROR como sigue: On error goto Label Cuando un error aparezca en tu programa Basic, AMOS saltara auto- maticamente a Label, que podra ser el punto de comienzo de una rutina de correccion de errores que puede localizar tu error y regresar sin problemas al programa principal. No olvides que de esa rutina debes salir usando una instruccion especial llamada RESUME. No esta permitido regresar al programa principal con una simple instruccion GOTO. Ejemplo: On error goto HELP DO Input "Introduce 2 numeros ";A,B Print A;" dividido por ";B;" es ";A/B Loop HELP: Print: Print: Bell Print" Me temo que has dividido por cero" RESUME next: Rem regresa a la siguiente instruccion Al objeto de que esto funcione bien, es esencial que un error no se presente dentro de la propia rutina correctora, de otro modo AMOS detendra la ejecucion de tu programa "irritado". Por otro lado, el efecto del comando ON ERROR GOTO puede ser anulado con el comando ON ERROR sin parametros a continuacion: On error: Rem evita la captura de errores 71 ON ERROR PROC (Captura un error utilizando un procedimiento) ON ERROR PROC Name Selecciona un procedimiento que sera llamado automaticamente si apareciera un error en el programa principal. Realmente es una version del comando anterior. Pese a que los procedimientos deben ser terminados mediante el comando END PROC, en este caso necesitaras para regresar al pro- grama principal, usar el nuevo comando RESUME, que sera localiza- do justo antes de la orden final END PROC. RESUME (reanuda la ejecucion del programa tras un error) Existen 5 formatos posibles para esta instruccion: RESUME. Regresa al comando que causo el error y lo ejecuta de nue vo. RESUME NEXT. Regresa a la instruccion inmediatamente a continua- cion de la que ocasiono el error. RESUME LINE. Salta a un punto especifico del programa principal. "Line" puede referirse a una etiqueta o a un numero de linea en concreto. Pero NO puede ser usado para volver a entrar a un proce dimiento. Los procedimientos se manejan de forma un tanto diferente. Si deseas saltar a un procedimiento en particular, tienes que situar un marcador especial en algun lugar del procedimiento para el chequeo de errores. Este metodo debe acompañarse del siguiente comando RESUME LABEL, del que existen 2 versiones distintas: RESUME LABEL label. Define a que etiqueta debe saltar tras la apa ricion de un error. Esta debe ser llamada despues de la rutina de manejo de errores, es decir justo despues de la orden ON ERROR PROC u ON ERROR GOTO. RESUME LABEL. Usado dentro de la rutina de manejo de errores para poder saltar a la rutina especificada en el comando previo. Ej.: On Error Proc HELP Resume Label AFTER Error 12 Print "Never Printed" AFTER: Print "He llegado aqui" End Procedure HELP Print "Hola, creo que existe un error" Resume label End Proc 72 ERRN (indica el numero del ultimo error) e=ERRN Cuando estes creando tus propias rutinas de manejo de errores con el comando ON ERROR, necesitaras ser capaz de conocer con preci- sion que tipo de error ha aparecido en tu programa. Asi, cuando un error ocurre, ERRN se carga automaticamente con su numero de identificacion. Mira el apendice de errores donde encontraras la lista completa de los errores posibles. ERROR (genera un error y regresa al editor) ERROR n La accion del comando ERROR es la de generar un error. Suponiendo que hayas creado un bonito error en las rutinas de manejo de erro res, este comando te permite simular un ERROR cualquiera que equi valga a cualquiera de los que se pudieran plantear, evitando asi la inconveniencia del error actual. Ejemplo: Error 40 Sale del programa e imprime el mensaje de error Label not defined Error Errn Esta orden usa la funcion ERRN para imprimir el error actual des- pues de que aparezca algun problema en tu programa. ================================================================ 73 8: T E X T O S Y V E N T A N A S Atributos de texto ================== PEN (Selecciona el color del texto) PEN Index La instruccion PEN establece el color de todo el texto que se mos trara en la actual ventana. Este color puede ser elegido entre 64 posibilidades diferentes dependiendo del modo grafico que estes usando en ese momento. Ejemplo: PEN 6 =PEN$(n) (Cambia el color PEN usando caracteres) a$=PEN$(n) PEN$ contiene una secuencia especial de control que cambia el co lor de texto dentro de una cadena. El nuevo color de texto sera asignado automaticamente cuando esta cadena se muestre en panta- lla. Ejemplo: C$=PEN$(2)+"WHITE "+PEN$(6)+"BLUE" Print C$ La cadena es devuelta por PEN$ en el formato: CHR$(27)+"P"+CHR$(48+n) PAPER (Selecciona el color del fondo de texto) PAPER Index Index puede ser un numero entre 0-63 =PAPER$(n) (Obtiene una secuencia de control para esta- blecer el color del papel) x$=PAPER$(index) PAPER$ obtiene un caracter de cadena que automaticamente cambia el color de fondo cuando aparece en pantalla. Por ejemplo: Pen 1: C$=PAPER$(2)+"WHITE "+PAPER$(6)+"BLUE " Print c$ INVERSE ON/OFF (activa modo inverso) INVERSE ON/OFF El comando INVERSE invierte los colores del texto y del fondo. 74 SHADE ON/OFF (Sombrea todo el texto siguiente) SHADE ON/OFF SHADE ON sobreimpresiona el texto al reducir la luminosidad de los caracteres con una especie de filtro. La sombra del texto puede a ser la normal mediante la orden SHADE OFF. UNDER ON/OFF (Activa el modo subrayado) UNDER ON/OFF UNDER ON subraya el texto que aparece en pantalla. UNDER OFF vuel ve al modo normal. WRITING (cambia el tipo de escritura) WRITING w1 ¡,w2¿ El comando WRITING te permite cambiar el modo de escritura utili zado para todas las siguientes operaciones de texto. Este comando determina la forma en la que tu nuevo texto debe ser combinado con los datos ya existentes en pantalla. w1=0 REPLACE (Default). El nuevo texto ocultara cualquier otra cosa por debajo. w1=1 OR Mezcla los caracteres con los de la pantalla mediante un OR logico. w1=2 XOR Los caracteres se combinan ahora con un XOR. w1=3 IGNORE Las operaciones de impresion seran ignoradas El segundo numero elige que parte del texto sera imprimida sobre la pantalla. Esta opcion puede ser omitida si se desea. w2=0 NORMAL El texto aparece en pantalla sobre el color del fondo w2=1 PAPER Solo el fondo del texto se dibuja en panta lla w2=2 PEN Ignora el color del papel y escribe el tex to en un fondo de color cero No confundas este comando con el GR WRITING, que ya veremos. 75 Funciones del cursor ==================== AMOS incluye una amplia gama de facilidades para maniobrar con el cursor a cualquier parte de la pantalla. LOCATE (posiciona el cursor) LOCATE x,y LOCATE x, LOCATE ,y El comando LOCATE mueve el cursor a las coordenadas x e y, esta bleciendo el punto de comienzo para cualquier operacion futura de impresion. Todas las posiciones de pantalla se especifican median te un "set" especial de coordenadas de texto. Dichas coordenadas son medidas en unidades que dependen del valor de la esquina supe rior izquierda de la pantalla. Asi por ejemplo, las coordinadas 15,10 hacen referencia a un punto 10 caraceres por debajo y 15 a la derecha. Si intentas imprimir algo fuera de los limites de la ventana, se generara un error. Ten en cuenta que la pantalla actual se con sidera siempre como ventana 0 (WINDOW 0); por lo que no necesitas abrir una ventana antes de usar esas funciones. CMOVE (Relativo al movimiento del cursor) CMOVE w,h Mueve el cursor a una distancia fija desde su actual posicion. Si el cursor estuviera en 10,10, entonces teclea: CMOVE 5,-5 y veras como el cursor aparece en 15,5. Al igual que en LOCATE, podras omitir alguna de las dos coordenadas requeridas. =AT (devuelve una secuencia de caracteres a la posicion del cursor) x$=AT(x,y) La funcion AT te permite cambiar la posicion del texto, directa- mente desde dentro de una misma cadena de caracteres. Funciona devolviendo una cadena en el formato siguiente: CHR$(27)+"X"+CHR$(27)+"Y"+CHR$(48+Y) Cuando esta cadena sea imprimida, el cursor del texto sera ubica- do en las coordenadas X e Y. Por ejemplo: