jueves, 22 de octubre de 2009

Sindarin returns

Debido a petición popular he puesto algunas cosas nuevas en Sindarin:

* Se ha implementado, de forma experimental, un botón para poder usar el modo nativo con cualquier ventana aunque no tenga el titulo adecuado. En la pestaña control junto al botón de "buscar uo" aparece uno que se llama "buscar otros", al pulsarlo sale una ventana con los nombres de las ventanas que Sindarin a podido descubrir,

* Implementado una monisima ventanita de "acerca de..."

* Se le han puesto ficheros de internacionalización, así que se traducirá automáticamente al ingles cuando el ordenador tenga ese idioma. También es posible editarlos para lograr que el Sindarin busque por defecto los títulos de ventanas de UO que nos plazca de forma automática.

* Se le añadió una lista de las instrucciones en el menú "Instrucciones", no estoy seguro que estén todos pero es un buen recordatorio.

* El comando "Component", que es nuevo ya funciona, sirve para poder consultar los componentes particulares de los colores y de las localizaciones un ejemplo de uso seria el siguiente:
Location barra_vida = [358, 325];
Color c = Color barra_vida;
Number verde = component 2 c

while (verde < 125) {
c = Color barra_vida
verde = component 2 c
print "No estamos muy verdes"
}
print "SuperVerdes"

Podéis bajarlo donde siempre:

Fichero binario:
http://sindarin.googlecode.com/files/Sindarin.jar
Fuentes y el proyecto(Netbeans 6.7.1):
http://sindarin.googlecode.com/files/Sindarin.tar.gz
http://sindarin.googlecode.com/files/Sindarin.zip

miércoles, 17 de septiembre de 2008

Algunas macros utiles en Sindarin

Macro para separar ores y quemarlos sobre la marcha:

Location vetas_minerales = [775, 440];
Location veta_mineral = [709, 476];
Location veta_mineral_para_quemar = veta_mineral - [0, 5] + [4,0];
number cant_minerales = 196;

repeat (cant_minerales - 3)
{
drag 1 vetas_minerales veta_mineral
}

repeat (cant_minerales - 3)
{
dclick left veta_mineral_para_quemar
wait 1
wait 400 msec
}

Y ahora con muchos comentarios que explican el funcionamiento:

# En esta localizacion tenemos los ores agrupados
Location vetas_minerales = [775, 440];

# En esta localizacion tenemos el sitio donde se pondran los minerales de 1 en 1
Location veta_mineral = [709, 476];

# Esta localizacion apunta a los minerales sueltos para ir quemando
# se calcula en las proximidades a la veta de mineral
Location veta_mineral_para_quemar = veta_mineral - [0, 5] + [4,0];

# El numero de minerales que vamos a separar quemar
number cant_minerales = 196;

# Aqui comprobamos que las localizaciones estan bien puestas
# descomentando el exit que esta mas abajo, tambien podemos mover un mineral para asegurarnos
mousemove vetas_minerales
wait 1
mousemove veta_mineral
wait 1
mousemove veta_mineral_para_quemar
#drag 1 vetas_minerales veta_mineral
#exit

# Separar la cantidad de ores menos 3, ya q cuando hay - de 3 vetas el objeto
# cambia de forma y se puede perder la localizacion
repeat (cant_minerales - 3)
{
drag 1 vetas_minerales veta_mineral
}

# Se queman tantos minerales como se han separado
repeat (cant_minerales - 3)
{
dclick left veta_mineral_para_quemar
wait 1 # espera un segundo
wait 400 msec # y 400 milisegundos
}

Todos los comentarios son explicativos y las pruebas no son necesarias, pero si utiles.


La típica macro de repetir constantemente la tecla F1:

wait 1 # Esperamos 1 segundo por si acaso
while true # Repetimos para esto para siempre
{
pkey 'f1' # Pulsa f1
wait 8 # esperamos 8 segundos hasta volver a pulsar
}



Tipica macro de construccion de dagas (o cualquier otro objeto):

Location armas = [250, 100];
Location flecha = [267, 92];
Location lejos = [500, 500];
Location arma = [90, 87]
Location tipo = [80, 87];

wait 1

repeat (40/3)
{
pkey 'F1'
wait 1

repeat 2
{
click left flecha
wait 1
mousemove lejos
}

dclick left armas
wait 1
dclick left tipo
wait 1
dclick left arma
wait 4
}


La misma con comentarios que explican el funcionamiento:

Location armas = [250, 100];
Location flecha = [267, 92];
Location lejos = [500, 500];
Location arma = [90, 87] # dagas
Location tipo = [80, 87]; # dagas

wait 1

# Intenta construir tantas dagas como pueda con 40 lingotes, suponiendo que
# se necesitan 3 lingotes por daga
repeat (40/3)
{
pkey 'F1' # Macro en ultima de lastobject, lasttarget
wait 1

# En el menu de herreria, hay que pulsar 2 veces(esto varia segun el server) sobre
# la flecha de la derecha para llegar a las armas de swordmanship
repeat 2
{
click left flecha
wait 1
mousemove lejos # x si sale el cuadrado negro explicativo
}

dclick left armas # Doble click sobre el menu de construccion de armas
wait 1
dclick left tipo # Doble click sobre armas de sword
wait 1
dclick left arma # Doble click sobre menu de las dagas
wait 4 # Esperamos 4 segundos, que acumulados a los que esperamos
# que al sumarse con los segundos que se espera para navegar
# de menu en menu son 9 segundos entre daga y daga
}



Macro para aplicar vendas de vez en cuando, que ademas comprueba que hora es y si son mas de las 11:30 de la mañana apaga el Uo y detiene el script:

number hora,minutos,segundos;
wait 1 sec
while true
{
time (hora,minutos,segundos);
if ((a >= 11) && (b >= 30))
{
wait 4
pkey 'alt'+'f4'
wait 1
exit
}
pkey 'f5'
wait 20
}


Y ahora con extras y explicaciones añadidas:


number hora,minutos,segundos; # Para guardar la hora
wait 1 sec
while true # Repetimos para siempre(o hasta q paremos el script)
{
time (hora,minutos,segundos); # Almacenamos la hora en las variables

# Mostramos la hora en la consola de mensajes
print "Son las " + hora+":"+minutos+":"+segundos

# Si son las 11:30 o mas tarde
if ((a >= 11) && (b >= 30))
{
beep # Hacemos sonar un beep
wait 4
pkey 'alt'+'f4' # Pulsamos Alt+F4 lo que cerrara el UO a lo bestia
wait 1
exit # Terminamos de ejecutar el script
}
pkey 'f5' # F5 es una macro lastobject-targetself
# que nos abremos acordado de aplicar vendas
# antes de empezar
wait 20 # Esperamos 20 segundos antes de volver a aplicar
}

jueves, 28 de agosto de 2008

El futuro...

El futuro no esta escrito que diría Sara Connor... pero desde luego esta muy negro...

Me gustaría que el avance de Sindarin fuese en esta dirección:
  1. En las versiones actuales de Sindarin poner el modo Nativo desactivado por defecto.
  2. Corrección de los diversos Bugs: En especial el bug que no impide la correcta llamada a otro script con parámetros.
  3. Mejorar el mecanismo de ejecución parada del script.
  4. Mejorar las capacidades de edición de Script.
  5. Independizar la GUI del sistema sobre el que corre.
  6. Eliminación del modo nativo: La arquitectura de Sindarin no estaba pensada para el modo nativo, este fue un añadido a ultima hora, y por las características del Api de win32, nunca podrá funcionar como debiera, así que creo que se convertido mas en un engorro que en una utilidad. Por otro lado el desconocimiento me ha impedido reescribirlo en linux, lo que tiene muchas e importantes consecuencias negativas alrededor de la portabilidad y usabilidad del programa bajo linux. Ademas se que nadie lo usa, así que nadie lo echara de menos en Sindarin.
  7. Implementación de Sindarin Lite: Aunque de la versión "grande" de Sindarin se elimine el modo Nativo, estaría bien poder diseñar he implementar un Sindarin "reducido" exclusivamente diseñado para funcionar en modo Nativo, lo que implicaría que este fork de momento seria inviable bajo linux.
  8. Reimplementacion del ScriptParser y CodeInterpreter: Para lograr que ambos módulos puedan trabajar de forma completamente independiente el uno del otro, de forma que se puedan usar por ejemplo distintas versiones de esos módulos sin que eso afecte al resultado final de forma negativa o que el GUI pueda ser independiente. La idea es conseguir que funcionen como un programa típico de linux:

    $ScriptParser script.sdr > salida.txt
    $CodeInterpreter salida.txt
    
    o bien:

    $ScriptParser script.sdr > CodeInterpreter
    
    de forma que el GUI únicamente seria la forma interactiva de llamar a ambos módulos.
  9. Escritura de un nuevo GUI: Un GUI esencialmente más atractivo y con una funcionalidad similar o superior. Me gustaría darle un aspecto similar a este: Aunque también se podría estudiar la forma de permitir diversidad de Skins.
  10. Implementación del comando "Component": Comando que permitiría el análisis de los componentes [R, G, B] de las variables "Color" y [X, Y] de las variables "Location" por separado, de forma que podamos saber directamente si el punto que analizamos es efectivamente mas o menos verde o saber en que coordenada X se encuentra exactamente nuestro ratón.
  11. Implementar la sentencia "switch": Para poder hacer scripts con muchas decisiones, mas elegantemente.
  12. Leer variables directamente del cliente: Realizar otro fork o modulo de ampliación que permita leer las variables directamente del cliente, como hace EasyUO, pero esto no puede ser una característica "base" de Sindarin, porque hay shards que no permiten los asistentes que leen directamente del cliente, así que debe ser posible no estar activa por defecto.
  13. Implementar un modulo de búsqueda y de patrones graficos: De forma que podamos buscar sobre la imagen cosas como la mochila o el paperdoll o cualquier cosa que nos de la gana, aunque si esta disponible la lectura de variables de cliente quizás esta ampliación o modulo sea redundante.
  14. Realizar una versión ejecutable de Sindarin que sea un fichero EXE, ya que por alguna razón a la gente le resulta complicado hacer funcionar un JAR.
  15. Utilizar la Api de java de internacionalización: Para que al menos el GUI este en varios idiomas y quizás implementar el lenguaje script de tal forma que hasta los comandos estén el el idioma natal del usuario, aunque esto habría que estudiarlo por las repercusiones a la hora del entendimiento e intercambio de scripts entre personas que podría tener.
Pero... La triste realidad es que no tengo tiempo, ni colaboración para hacer nada de esto, por eso el futuro de Sindarin es muy negro, a menos que me despidan o me vuelva loco y use todo mi tiempo libre para Sindarin. Otra posibilidad seria que alguien que supiese de programación y preferentemente de Java o estuviese dispuesto a hacer el esfuerzo, comenzara a colaborar conmigo, en ese caso quizás me plantearía volver a coger el proyecto con fuerza.

miércoles, 27 de agosto de 2008

Explicación exhaustiva...

Finalmente el ultimo texto rescatado del baúl de los recuerdos:

Sintaxis de Sindarin en formato BNF y explicación exhaustiva de los comandos (revisado).

También puede interesarte:



  1. El comienzo...
  2. Códigos...
  3. Lista de todos los comandos
  4. wait
  5. iodelay
  6. say
  7. keypress
  8. keyrelease
  9. pushkey
  10. click
  11. dclick
  12. mousemove
  13. mousepress
  14. mouserelease
  15. drag
  16. if
  17. while
  18. repeat
  19. break
  20. exit
  21. print
  22. beep
  23. date
  24. time
  25. call
  26. igualación
  27. declaración de variables
  28. Expresiones aritméticas y booleanas
  29. Miscelánea


  1. El comienzo...

    Un programa Sindarin consta de dos partes, definición de variables y códigos, ambas opcionales.
    La declaración de variables debe hacerse obligatoriamente al principio del script.

    La definición BNF es:

    { declaración de variables } {códigos... }
  2. códigos...

    Esta parte estará compuesta por un comando seguido o no por un ";" o una lista de comandos encerrados entre corchetes "{" "}" o palabras claves "begin" "end".

    La definición BNF es:

    comando [";"] | "{" {state [";"]} "}" | "begin" {state [";"]} "end"
  3. Lista de todos los comandos

    Más abajo se detallan pormenorizadamente cada uno de los comandos aquí una enumeración de todos los comandos:


    • wait: Ejecuta una pausa en la ejecución.
    • iodelay: Modifica la pausa automática que se realiza tras cada comando de entrada/salida de teclado o ratón.
    • say: El pj dice algo.
    • keypress: pulsa una macro y la mantiene pulsada.
    • keyrelease: libera la pulsación de una macro.
    • pushkey: pulsa una macro y la suelta, equivalente a click para el teclado.
    • click: Simula un click en un punto de pantalla.
    • dclick: Simula un doble click en un punto de pantalla.
    • mousemove: mueve el cursor del ratón a una posición de pantalla.
    • mousepress: un botón del ratón y lo mantiene pulsado.
    • mouserelease: libera la pulsación de un botón del ratón.
    • drag: mueve una cantidad de objetos desde una localización a otra.
    • if: hace un comprobación y ejecuta un código si esta es cierta o no sino lo es.
    • while: repite el/los códigos que están a continuación mientras se cumpla una condición.
    • repeat: repite el comando o los comandos encerrados entre "{","}" o "begin", "end" tantas veces como indique la expresión numérica puesta a continuación.
    • break: Sale de un bucle repeat o while en caso de encontrarse dentro de uno.
    • exit: Termina el programa.
    • print: Imprime en la consola de mensajes la expresión puesta a continuación.
    • beep: Emite un sonido de alerta.
    • date: Introduce en las variables colocadas a continuación el día, mes y año actual, según la fecha del equipo.
    • time: Introduce en las variables colocadas a continuación la hora, minutos y segundos de la hora del sistema.
    • call: Ejecuta otro script Sindarin.
    • Aunque no es un comando propiamente dicho si se coloca una variable seguida de "=" se introduce en ella el valor de la expresión siguiente.
  4. wait (esperar...)

    Realiza una pausa en la ejecución del programa.

    La sintaxis es: "wait" seguido de una expresión numérica que indica la cantidad de tiempo a pausar,
    seguida de la unidad de tiempo.

    Las unidades de tiempo se miden en minutos "min", segundos "sec" y milisegundos "milisec" "msec", en caso de no especificar ninguna se supondrá que la unidad de tiempo es el segundo.

    La definición BNF es:

    wait expresión_numérica ([sec] | min | milisec | MSEC)
  5. iodelay (retrazo de entrada salida)

    Las instrucciones de entrada salida(mousepress, click, pushkey...) realizan automáticamente un pausa al terminar
    , por defecto esta pausa es de 4 milisegundos, con este comando esta cantidad se puede variar usando este comando.

    La sintaxis es: "iodelay" seguido de una expresión numérica que indica la cantidad de tiempo a pausar,
    seguida de la unidad de tiempo.

    Las unidades de tiempo se miden en minutos "min", segundos "sec" y milisegundos "milisec" "msec", en caso de no especificar ninguna se supondrá que la unidad de tiempo es el segundo.

    La definición BNF es:

    iodelay expresión_numérica ([sec] | min | milisec | msec)
  6. say (decir)

    Esta instrucción hace que el PJ diga algo en el Ultima Online. La sintaxis de esta instrucción es say seguido de una expresión de texto.

    La definición BNF es:

    say expresión_textual
  7. keypress (Presiona tecla)

    Simula la pulsación de una o varias teclas especificadas por una expresión de tipo Macrokey(macro de tecla),
    este comando no realiza la liberación de la tecla, es decir mientras no se llame al comando Keyrelease con la misma expresión de tecla o bien a un comando de tipo
    Pushkey, que realiza un pulsación y luego la liberación, sobre el mismo conjunto de teclas.

    Este comando puede escribirse además de las siguientes maneras: kpress.

    La definición BNF es:

    keypress expresión de tipo tecla
  8. keyrelease (Libera tecla)

    Simula la liberación de una o varias teclas que se encuentren pulsadas por la llamada a un comando Keypress, este comando es el complementario de Keypress.

    Este comando puede escribirse además de las siguientes maneras: krelease, krel.

    La definición BNF es:

    keyrelease expresión de tipo tecla
  9. pushkey (pulsar tecla)

    Simula la pulsación y posterior liberación de una o varias teclas, es como llamar consecutivamente a Keypress y luego a Keyrelease sobre el mismo conjunto de teclas.

    Este comando puede escribirse además de las siguientes maneras: pkey, key.

    La definición BNF es:

    pushkey expresión de tipo tecla
  10. click

    Realiza la simulación de un click del ratón sobre un punto especifico de la ventana, es equivalente a
    realizar un Mousemove, seguido de un Mousepress y un Mouserelease con el mismo botón y sobre la misma localización.

    La definición BNF es:

    click (left | right) expresión de tipo Location(Localización de pantalla)
  11. dclick

    Realiza la simulación de un doble click del ratón sobre un punto especifico de la ventana, es equivalente a
    realizar dos click consecutivos el mismo botón y sobre la misma localización.

    Este comando puede escribirse además de las siguientes maneras: doubleclick.

    La definición BNF es:

    dclick (left | right) expresión de tipo Location(Localización de pantalla)
  12. mousemove (mover ratón)

    Este comando mueve el cursor del ratón desde su posición actual hasta la posición indicada a continuación.

    Toda la familia de comandos Mouse...(Mousemove, Mousepress y Mouserelease) tienen problemas en modo nativo,
    si se usan con la ventana de Ultima maximizadas. Para evitar estos problemas lo mejor es minimizar la ventana de Ultima o bien
    desactivar el modo nativo.

    Este comando puede escribirse además de las siguientes maneras: mmove.

    La definición BNF es:

    mousemove expresión de tipo localización
  13. mousepress (presiona ratón)

    Este comando simula la pulsación del botón colocado a continuación del comando, pero no su liberación,
    por lo que permanece pulsado hasta que se ejecute el comando Mouserelease sobre dicho botón o un comando
    de tipo click o dclick que implícitamente realizan un Mouserelease.

    Toda la familia de comandos Mouse...(Mousemove, Mousepress y Mouserelease) tienen problemas en modo nativo,
    si se usan con la ventana de Ultima maximizadas. Para evitar estos problemas lo mejor es minimizar la ventana de Ultima o bien
    desactivar el modo nativo.

    Este comando puede escribirse además de las siguientes maneras: mpress.

    La definición BNF es:

    mousepress (left | right)
  14. mouserelease (Libera ratón)

    Este comando simula la liberación de un botón que a sido atrapado usando el comando mousepress, este comando es su complementario.

    Toda la familia de comandos Mouse...(Mousemove, Mousepress y Mouserelease) tienen problemas en modo nativo,
    si se usan con la ventana de Ultima maximizadas. Para evitar estos problemas lo mejor es minimizar la ventana de Ultima o bien
    desactivar el modo nativo.

    Este comando puede escribirse además de las siguientes maneras: mrelease, mrel.

    La definición BNF es:

    mouserelease (left | right)
  15. drag

    Este comando sirve para mover una cantidad de objetos desde una localización a otra. Debe ir seguido de una expresión numérica
    que indique el numero de objetos a mover, pudiendo ir seguido de la palabra "objets" que no cumple ninguna finalidad y es prescindible,
    una expresión de tipo localización que indique donde se encuentran en principio los objetos, que puede
    ir seguida de la palabra "from", que también es prescindible, y otra m que indique donde hay que soltarlos.

    La definición BNF es:

    drag expresión numérica [OBJECTS] expresión de tipo location(Localización) [FROM] expresión de tipo location(Localización)

    Desde la versión 0.3, se ha añdido la opción de usar "ALL" en lugar de una cantidad a mover lo que mueve todos los objetos.

    La definición BNF es:

    drag [ expresión numérica| ALL ] [OBJECTS] expresión de tipo location(Localización) [from] expresión de tipo location(Localización)
  16. if

    "If" evalúa una expresión colocada inmediatamente después, si esta expresión es 0 supondrá que es falsa y no se ejecutaran las sentencias colocadas a posterioridad,
    si la expresión es distinta de 0 se ejecutara la/las sentencias colocadas a continuación.

    La sentencia If puede ir seguida de la clausula "else", si la expresión evaluada por if es falsa entonces se ejecutara la/s sentencias colocadas a continuación de else.

    Existen las variables de entorno true y false, cuyo valor es respectivamente 0 y 1, con lo cual una sentencia del tipo: "if true { comandos 1 } else { comandos 2 }" ejecutara siempre
    "{ comandos 2 }" mientras que la sentencia: if false { comandos 1 } else { comandos 2 }" ejecutara siempre "{ comandos 2 }".

    If espera evaluar siempre una expresión numérica, por lo tanto se pueden usar cualquiera de los operadores aritméticos que se contemplan en las expresiones normales, sin embargo existen
    una serie de operadores especí­ficos pensados para las sentencias de evaluación(aunque pueden insertarse en cualquier expresión aritméticos normal).

    La definición BNF es:

    if expresión booleanas ( { comandos } | begin comandos end | comando ) [ else ( { comandos } | begin comandos end | comando ) ]
  17. while (mientras)

    Este comando permite ejecutar varias veces un digo colocado a continuación, la lógica de este comando es la siguiente: mientras la expresión booleana colocada a continuación sea verdadera se continuara ejecutando
    lo/s comandos colocados inmediatamente después. Así por ejemplo seria posible construir un bucle infinito de la siguiente manera: "while true { comandos }" que significar que mientras true(verdadero) sea verdadero entonces se ejecutar
    "{ comandos }" puesto que true siempre es verdadero "{ comandos }" se ejecutar para siempre.

    Otro ejemplo de construcción valida seria:

    while (color [100, 100] = color1)
    say "hola"
    

    lo que obligar al jugador a decir "hola" mientras el color de la Location [100, 100] fuese distinto de la variable color1.

    La definición BNF es:

    while expresión booleana sea cierta ( { comandos } | begin comandos end | comando )
  18. repeat (repetir)

    Este comando permite ejecutar varias veces un digo colocado a continuación, la lógica de este comando es la siguiente: repetir un numero finito de veces, especificado en una expresión numérica, el digo colocado a continuación.

    Un ejemplo de construcción valida seria:

    Number a = 50;
    repeat (a/2) times
    say "hola"
    
    lo que obligar al jugador a decir "hola" 25 veces.

    Otro ejemplo de construcción valida seria:

    repeat 100
    begin
    drag 1 object [100,100] from [200,200]
    end
    
    Que obligar a mover un objeto desde la posición [100,100] hasta la [200,200] cien veces consecutivas.

    Otro ejemplo de uso seria:

    repeat 10
    {
    pushkey 'F1'
    wait 1 min
    }
    
    Que obligar a pulsar 'F1' 10 veces con un retraso de un minuto entre pulsación y pulsación.

    La definición BNF es:

    repeat expresión numérica [times] ( { comandos } | begin comandos end | comando )
  19. break (Romper)

    Interrumpe la ejecución de un bucle, si colocamos break dentro de un bucle y se alcanza el break, se sale del bucle.

    Un ejemplo de utilización seria:

    while (true) {
    say "hola"
    break
    }
    
    El "hola" solo se ver una vez ya que al llegar al break se terminar el bucle infinito.

    Otro ejemplo de uso seria:

    Location nightshade = [100, 100]
    Color verde = [0, 255, 0]
    repeat 10000
    {
    pushkey 'a'
    wait 1
    if (verde != color nightshade)
    break
    }
    Este bucle pulsar diez mil veces la tecla 'a', a menos que la Location "nightshade" no tuviera el color "verde".

    La definición BNF es:

    break
  20. exit (salir)

    Si durante la ejecución de un código se encuentra el comando "exit" se termina la ejecución, es como si se le hubiese dado al botón de "Stop".

    La definición BNF es:

    exit
  21. print

    Imprime en la consola de mensajes la expresión siguiente.

    La definición BNF es:

    print expresión
  22. beep

    Emite un sonido de alerta.

    Disponible desde la versión 0.3

    La definición BNF es:

    beep
  23. date (fecha)

    Este comando carga en tres variables/parametros pasados entre parentesis y separados por comas, la fecha del sistema.

    En el primer var/parametro numérico de la función se mete el año del sistema, en el segundo el mes y en el tercero el día.
    La definición BNF es:

    date "(" año "," mes "," día ")"
  24. time (hora)

    Introduce en los tres parametros variables siguientes la hora del sistema, estos parametros han de estar entre parentesis y separados por comas.

    La definición BNF es:

    time "(" hora "," minuto "," segundo ")"
  25. call

    Ejecuta otro script de Sindarin, el script se define con una cadena de texto tras el comando call que contendrá el camino al fichero, el script llamador puede enviar parámetros al script llamado.
    Los parámetros han de pasarse entre parárentesis y separados por comas, solo es posible pasar literales, variables o parámetros, las expresiones complejas no están permitidas como parámetro. Si el parámetro pasado es una variable o un parámetro, las modificaciones que se realicen dentro del script llamado tendrán efecto en las variables del llamante.

    Dentro del script se referencia los parámetros como "$" seguido de un numero, de forma que "$1" seria el primer parámetro pasado, "$2" el segundo, no existe limitación en cuanto a el número de parámetros.

    Hay que tener precaución en tanto en cuanto no se hace ninguna comprobación del tipo de parámetro pasado, es decir si el script llamante pasa un numero 1 y el script llamado esperaba un texto no se emitirá error hasta el momento de usar el parámetro, pudiendo darse el caso de que no se emita error debido a que el contexto de uso permita el uso de distintos tipos de variables, aunque evidentemente funcionara mal.
    Tampoco se realiza una comprobación del numero de parámetros por lo que se podrá llamar a un script que esperase 3 parámetros sin ninguno, lo que emitirá un error en el script llamado.

    Este comando puede escribirse además de las siguientes maneras: @

    La definición BNF es:

    call "camino hasta el script" ["("lista de parametros separados por comas")"]
  26. igualación

    Operador de igualación, colocamos una variable de cualquier tipo seguida de símbolo "=" y de una expresión del mismo tipo que la variable/parametro y esta toma el valor dado por la expresión.

    La definición BNF es:

    (variable | parametro) = expresión
  27. declaración de variables

    Las variables tienen un nombre y un valor, el nombre a de comenzar por "_" o letras y a de ir seguido por una o mas letras, dígitos y "_"
    La declaración de variables se ha de realizar obligatoriamente al principio del script. Los distintos tipos de variables son los siguientes:

    • Number: son aquellas variables que pueden tomar valores numéricos de tipo entero, superiores a 0. Ejemplo:

      Number a=1, b=2
      Number c = a + b
      
    • String: son variables que pueden tomar valores de tipo textual encerradas entre ". Ejemplo:

      String nombre_vendedor = "marlon";
      String comprar = nombre_vendedor + " buy";
      
    • Location: son variables que toman posiciones de pantallas, representadas en dos coordenadas X e Y, encerradas entre [] y separados por comas. Ejemplo:

      Location localizacion_mochila = [100, 100];
      
    • Macrokey: son variables que pueden tomar valores entre una y cuatro teclas, donde cada una de las teclas se han de encerrar entre ' y para aumentar el numero de teclas representadas en una macrokey han de ser sumadas, un ejemplo de declaración:

      Macrokey pulsar_f1_y_f2 = 'f1' + 'f2'
      
      Puesto que salvo las teclas simples (números y letras) las demás se representan por una cadena de texto es especialmente y recomendable usar las facilidades de inicialización de Sindarin
    • Color: representa un color de pantalla, el color debe especificarse en formato RGB, donde cada una de las componentes han de estar encerradas entre [] y separadas por comas. Un par ejemplos de declaración e inicialización son:

      Color rojo = [255, 0, 0];
      Color color_mochila = color localizacion_mochila;
      
      
      
    La definición BNF es:

    ( number | string | location | macrokey | color ) nombre_var1 [ "=" expresión de inicialización ]] {"," nombre_varN [ "=" expresión de inicialización ]]} [";"]
  28. Expresiones aritméticas y booleanas

    Sumas, restas...
    Operadores Aritméticos:

    • "+": Suma dos operadores: Es posible sumar cualquier variable con cualquier variable, siempre que sean del mismo tipo, salvo las variables de tipo String que al ser sumadas con cualquier otra producen un resultado de tipo String.
      Las variables de tipo Location, y color al ser sumadas se suman como si se sumaran elemento a elemento cada una de sus componente, es decir la Location [100, 100] + [50,50] crearían una Location [150,150].
      Al sumar colores si el rango de cualquier suma sobrepasa el 255, que es el máximo rojo o verde o azul, es decir si sumamos [255, 255, 255] + [1 ,1 ,1], esto sobrepasaría el limite máximo, así que se redondea a [255, 255, 255].
      Las variables tipo Macrokey generan una Macrokey tal que al pulsarla seria como pulsar las dos sumadas a la vez: ejemplo:

      Macrokey a = 'a'; a = a + 'F1'; pkey a;

      Esto generaria una pulsación de 'a' y 'F1' a la vez.
    • "-": Resta dos operadores: También es posible restar cualquier variable con cualquier otra del mismo tipo, excepto las de tipo String, esas no es posible restarlas con nada.
      Igualmente tanto Locations como Colors se restan componente a componente.
      Si una componente de un Color al restar llegase a un numero negativo: [0,0,0] - [1,1,1], el resultado se redondearía a [0,0,0].
      Las variables de tipo Macrokey al restar una a otra genera una macrokey como el primer operador pero sin la/s teclas del segundo, en caso de que la/s teclas del segundo no existiesen en el primer operando no se hace nada:

      Macrokey a = 'F1'+'F2';
      Macrokey b = a -'F2';
      Macrokey c = a -'F3';
      key a
      key b
      key c
      

      Al pulsar a se pulsarían simultaneamente la tecla 'F1' y 'F2', al pulsar b se pulsaría solo 'F1' y al pulsar c se pulsaría de nuevo 'F1' y 'F2'

    • "*": Multiplica dos operadores, solo es posible multiplicar Números con Números.
    • "%": Calcula el modulo de dos operandos, solo es posible calcular el modulo de dos números.

    Es posible realizar operaciones del tipo:

    Number a = 1 + 2 * 3 + 8 * (15 + 1)/2
    Number b = (1 + 2)*((a + 8)*(15 + 1)/sindarin_version)
    String c = "hola " + Manolito + 15
    Location d = [100, 100] - [25,25] + [10,10]
    

    Nótese que en a se calcularía 1 + (2 * 3) + (8 * (15 + 1)/2) dado que el orden de precedencia de los operadores *, / y % son los esperados.
    Y como podemos ver en b se pueden usar variables predefinidas en los cálculos.

    Evaluación de condiciones:

    Operadores relacionales:

    • "<" operador "menor que", devuelve true si la expresion inmediatamente anterior es menor que la siguiente a el.
    • ">" operador "mayor que", devuelve true si la expresión inmediatamente anterior es mayor que la siguiente a el.
    • "<=" operador "menor o igual que", devuelve true si la expresion inmediatamente anterior es menor o igual que la siguiente a el, tambi puede escribirse como "=<".
    • ">=" operador "mayor o igual que", devuelve true si la expresión inmediatamente anterior es mayor o igual que la siguiente a el, también puede escribirse como "=>".

    Estos operadores solo pueden evaluar expresiones numérica, cualquier otro tipo de expresión emitirán error.

    Sin embargo existen las dos siguiente expresiones:

    • "=" operador "igual que",devuelve true si la expresión colocada antes del "=" es igual a la colocada después, también puede escribirse de la siguiente manera: "==".
    • "!=" operador "distinto de", devuelve true si la expresión colocada antes del "!=" es distinta a la colocada después, también puede escribirse de la siguiente manera: "<>".

    Estos dos operadores pueden aplicarse a cualquier tipo de expresión.

    Existen también operadores booleanos que permiten relacionar varias expresiones entre si:

    • "&" operador "Y", devuelve true si las expresiones colocada a ambos lados son verdaderas(distintas de 0) y devuelve false en el caso de que alguna de las dos fuese falsa. Puede escribirse "&&" y "and"
    • "|" operador "O", devuelve true si alguna de las expresiones colocada a ambos lados es verdadera(distintas de 0) y devuelve false en el caso de que ambas sean falsas. Puede escribirse "||" y "or"

  29. Miscelánea


    • Comentarios: los comentarios han de comenzar por el carácter #, el resto de la linea sera ignorado por Sindarin
    • isnativemode: Puede usarse dentro de una expresión, devuelve true si esta funcionando correctamente el modo nativo, ejemplo:
      if (isnativemode == false) print "A ocurrido algún error con la ventana de Ultima". También puede escribirse isnatmode.
    • Color: Además de usarse para definir el tipo Color también sirve para saber que color una localización precisa, ejemplo:

      if (color loc1 != [1,1,1]) say "a cambiado el color"

      Con la ventana minimizada no funciona, ni siquiera
      en modo nativo,es necesario que el punto a evaluar
      este en primer plano.
    • Component: se usa para poder diferenciar cada uno de los componentes básicos de colores o localizaciones, ejemplo:

      Location barra_vida = [358, 325];
      Color c = Color barra_vida;
      Number verde = component 2 c
      
      while (verde < 125) {
      c = Color barra_vida
      verde = component 2 c
      print "No estamos muy verdes"
      }
      print "SuperVerdes"

    • true: es una variable predefinida con el valor 1, para facilitar el uso en comandos de evaluación, ejemplo:
      while (true) say "Siempre se ejecuta..."
    • false: es una variable predefinida con el valor 0, para facilitar el uso en comandos de evaluación, ejemplo:
      if (false) print "nunca llega" 
    • sindarin_version: variable predefinida de tipo Number, que contiene el numero de la versión de Sindarin corriendo en el momento, ejemplo:
    • if sindarin_version < 1 print "Esta version no es definitiva"
    • sindarin_revision: variable predefinida con la revisión del sindarin en que esta corriendo, ejemplo:
      if (sindarin_revision != 0) say "Usando una versión beta de Sindarin"
    Las variables predefinidas no pueden ser modificas, 
    ante cualquier intento se emitirá un error

martes, 26 de agosto de 2008

Tutorial para muy novatos

Otro texto que escribí hace tiempo en relación a Sindarin, esta vez es un tutorial, muy simple:

Tutorial para muy novatos...(Revisado)

Vamos a aprender a hacer scripts, muy, muy sencillos...

click:

Este comando sirve para que se haga un click con el ráton en un punto de pantalla, para usarlo basta con poner "click" seguido de "left" (izquierdo en ingles) si quieres que use el botón izquierdo del ratón o "right" (derecho en ingles) y después tienes que poner el punto donde quieres que se haga "click". Por ejemplo:

click left [100,100]
click right [500,500]

Eso si, el punto tienes que escribirlo entre corchetes y separado por una coma [ , ] por que si no, no funcionara. Ya esta, eso es todo. Quizás tengas alguna duda de como averiguar el punto en el que quieres hacer click, para eso usa el botón capturar de la pestaña "location":


Si pulsas en "Capturar" y luego donde quieres que se haga click saldrán los números en donde pone X e Y. ¿Fácil verdad?

dclick:

Supongamos que queremos hacer un doble click con el ratón(pulsar dos veces muy rápido) para ello usamos este comando, que funciona igual que el anterior, escribes "dclick" seguido de "left" si quieres que el click se haga con el botón izquierdo o "right" si quieres que se haga con el derecho y luego pones el punto donde quieres que se haga, por ejemplo:

dclick left [25, 25]
dclick right [25, 25]

para ver el punto usa el botón capturar de la pestaña Location, como en click.

wait (esperar...)

¿Necesitas que el programa se pare un poco entre comando y comando? Para ello usa el comando "wait", escribes "wait" seguido de un numero de segundos que quieres que Sindarin se pare y ya esta por ejemplo:

wait 30

También puede hacer que se pare un numero de minutos:

wait 1 min
wait 15 min

pushkey (pulsar tecla)

Para que se pulse una tecla, para por ejemplo usar una macro, para ello escribimos "pushkey"(pulsar tecla en ingles) seguido de la tecla entre comillas simples 'tecla' por ejemplo:

pushkey 'a'
pushkey '1'
pushkey 'F1'
pushkey 'F12'

Aquí vemos como pulsamos la tecla "a", el "1", la tecla de función "F1" y la "F12".

Este comando es un poco largo de escribir, pero se puede escribir de varias formas, aunque hacen lo mismo:

pkey 'f5'
pkey 'b'
key 'C'
key '3'

Aquí hemos pulsado la tecla de función "F5", luego la "b", luego la "c" y por ultimo el "3", se puede escribir de cualquiera de esas formas y hará lo mismo.

drag (arrastrar)

¿Que pasa si queremos mover objetos de un sitio a otro?, tenemos el comando "drag", que sirve para mover objetos. Funciona escribiendo "drag" seguido de un numero, que sera el numero de objetos que vamos a mover, luego un punto donde estarán los objetos al principio y luego un punto donde queremos que deje los objetos, por ejemplo:

drag 1 [100,100] [25,25]
drag 12 objects [103,10] [205,25]
drag 25 [3,3] [2,2]

Primero movemos un objeto desde el punto [100,100] hasta el [25,25], luego movemos doce objetos desde el [103, 10] hasta el [205, 25], la palabra "objects" solo sirve para que sea mas fácilmente comprensible, no es realmente necesaria, y finalmente movemos veinticinco objetos desde [3,3] hasta [2,2].

Los puntos los podemos averiguar como hacíamos en el comando "click".

repeat (repetir)


Supongamos que queremos hacer una macro que pulse cuatro veces la tecla "F12" y haga una pausa de un segundo, por ejemplo:

pushkey 'F12'
wait 1
pushkey 'F12'
wait 1
pushkey 'F12'
wait 1
pushkey 'F12'
wait 1

Esto lo haría, pero... ¿no hay una forma de hacer que sindarin repita eso 4 veces sin que yo tenga que escribir cuatro veces lo mismo? Si para eso es el "repeat", funciona poniendo "repeat" seguido del numero de veces que quieres que se repita algo, luego el signo "{", luego los comandos que quieres que se repitan y terminas con otro símbolo "}", el ejemplo anterior nos quedaría así:

repeat 4
{
pushkey 'F12'
wait 1
}

Ya esta, no es muy complicado...

"Bufff pero eso del símbolo { y el símbolo } es un poco feo... ¿no?"

También puedes sustituir "{", "}" con "begin" y "end", así:

repeat 4
begin
 pushkey 'F12'
 wait 1
end

Cualquiera de las dos formas de escribirlo funcionara.

while (mientras)

"Vaya parece que solamente me ejecuta el script una sola vez, si escribo:"

pkey 'F1'
wait 1

"Solo me pulsa 'F1' una vez  y se detiene...¿Como puedo hacer que el script se repita muchas veces?"

La solución es usar "while" o "repeat" podrías poner un "repeat" muy grande:

repeat 40000
{
 pkey 'F1'
 wait 1
}

es decir, pones todo lo que quieres que se repita dentro de un "repeat" muy grande, en este caso se repetiría cuarenta mil veces, pero otra solución mucho mas elegante es:

while true
{
 pkey 'f1'
 wait 1
}

"While" sirve para repetir muchas veces unos comandos pero que en vez de repetirse un numero de veces se repite mientras se cumpla la condición escrita tras el. En el ejemplo como la condición de "while" es "true" (que significa que siempre es verdad), este código se repetiría para siempre, ¡¡Seria infinito!!


Teóricamente "while" no terminaría nunca, mientras que "repeat" se repite una serie de veces, pero en la practica es difícil que llegue a repetirse cuarenta mil veces, pero... nunca se sabe, además el "while" es mas elegante.

Pero... ¿como parar ese código infinito?

Bueno hay comandos que permiten detener el script:
  • "Break": Dentro del "while" haria que este terminara y por lo tanto el script.
  • "exit": En cualquier parte del script para totalmente el script.
En la ventana de Sindarin existen dos formas de parar cualquier código, pulsando el botón naranja de "Stop":

O manteniendo pulsado un tiempo (un segundo suele ser suficiente) la tecla "Pause/Break":

Esto ultimo solo funciona en Windows.

Bueno... Con esto ya podrías escribir tus propios scripts de forma sencilla, ahora si quieres profundizar y hacer cosas mas complicadas puede que te sean útiles estos dos post:


  1. Una explicación de todos los comandos de Sindarin.
  2. Algunas macros que me eran útiles en mis tiempos...