Juego de la Escoba con jugador controlado por el ordenador Jesús Padilla Hidalgo Universidad Carlos III Madrid Avda. de la Universidad 30, Leganés Madrid,España [email protected] Resumen Palabras clave Juego de la escoba, IA,JAVA. 1.INTRODUCCIÓN 1.1 El juego de la escoba La escoba es un antiguo juego italiano (su origen se remonta al siglo XVI), cuyo nombre original es Scopa. Este juego pertenece a un grupo en el que los jugadores tratan de «capturar» o «pescar» cartas que hay sobre la mesa utilizando las que tienen en la mano, bien formando combinaciones especiales, bien por la relación de la carta de la mano con las descubiertas sobre la mesa que se recogen. Existen diversas variantes de la escoba: la escoba propiamente dicha, la escoba de quince, la escoba científica. Fuera de Italia, la escoba por antonomasia es la escoba de quince. 1.2 Reglamento El objetivo del juego es conseguir el máximo de puntos gracias a las cartas capturadas. Las partidas de escoba se disputan entre dos, tres o cuatro jugadores. Cuando son dos o tres los jugadores, cada uno de ellos juega individualmente para sí mismo; en cambio, cuando los jugadores son cuatro suelen formar dos parejas que juegan en equipo. También pueden tomar parte seis jugadores que deben formar tres parejas de jugadores. Para jugar a la escoba se utiliza la baraja italiana de 40 cartas, que es igual en contenido -aunque de dibujos distintos- a la española. También puede utilizarse una baraja inglesa adaptada, es decir, sin los ochos, los nueves ni los dieces. En realidad, dado que el valor de las cartas durante el juego va del uno al diez, es más sencillo utilizar una baraja inglesa sin figuras (de este modo se puede dar a cada carta el valor de su índice). En caso de utilizar una baraja española, puede tomarse la de 48 cartas y retirar los caballos y los reyes, con lo que quedan cuarenta cartas, cuyos índices van del 1 al 10. El juego comienza repartiendo el mazo en tres cartas para cada jugador y poniendo cuatro cartas boca arriba sobre el tapete. Es jugador que empieza (la mano) es el que se encuentra a la derecha del que reparte (el pie) y por lo tanto el primero en jugar una carta para intentar hacer baza. Un jugador juega la carta que más le convenga de entre las que tiene en la mano, poniéndola sobre el tapete y tratando de sumar 15 puntos con esta carta y cuantas pueda de las que están en la mesa. Si lo consigue recoge las mismas, dejando sobre el tapete las cartas sobrantes (las cartas que se recogen se sitúan en un montón junto al jugador boca abajo). Si consigue sumar 15 puntos con todas las cartas del tapete se dice que ha hecho una escoba. En ese caso al recoger las cartas para ponerlas con el resto de las bazas ganadas se suele poner una de las cartas boca arriba y cruzada con el resto de sus cartas a modo de marca para poder contar al final de la mano los puntos ganados. Como es lógico el siguiente jugador después de una escoba no podrá hacer baza y se limitará a poner una carta sobre el tapete. Cuando el jugador que reparte las cartas se encuentra que las cuatro que ha descubierto sobre el tapete suman 15, se dice que tiene escoba de mano, y pasa a adjudicarse la baza como propia señalando además la escoba conseguida. También puede darse el caso de que se encuentre con que estas cuatro cartas formen dos pares de cartas que suman 15 cada par, en ese caso habrá conseguido dos escobas de mano, ganando ambas bazas de salida. Además si las primeras dos suman 15 a pesar que las 2 cartas siguientes no lo sumen las primeras van a formar escoba y pasan a la baza del jugador. Por último, una vez jugadas las tres cartas de cada jugador repartidas inicialmente, el encargado de repartir (el pie), dará tres cartas más a cada uno en el mismo orden que se hizo antes, pero sin poner ninguna sobre el tapete, ya que en éste habrán quedado las sobrantes de las bazas anteriores. A continuación se procede del mismo modo a jugar sus cartas cada jugador y a repartir otras tres hasta que se haya finalizado el mazo. Cuando todos los jugadores han jugado sus cartas y no quedan más para repartir, habrán quedado sobre el tapete una o varias cartas con las cuales es imposible sumar 15. En ese momento se ha de verificar que las cartas sobrantes suman 10, 25, 40 ó 55, esto es matemáticamente cierto y de no ser así indicaría que alguno de los jugadores ha cometido un renuncio en alguna de sus jugadas. Si efectivamente suman una de esas cantidades, serán recogidas por el jugador que ganó baza por última vez y las contará como suyas en el recuento final de puntos. 1.3 Recuento de los puntos Una vez agotadas las cartas se procede al recuento de los puntos: •Un punto por cada escoba. •Un punto al que tiene más cartas, más otro adicional si los restantes jugadores tienen, todos ellos, menos de 10 cartas. Ejemplo: •Un punto al que tiene más sietes, o por tener setenta, también llamado primera: la mayor suma de 4 cartas menores de 8 de diferentes palos. El punto que se disputa depende de las reglas locales; más un punto extra si se tienen los 4 sietes de la baraja. import java.applet.Applet; •Un punto al que tiene más oros. 2 puntos en caso de tener todos los oros. { import java.awt.Graphics; public class HolaMundo extends Applet public void paint(Graphics g) { •Un punto si tiene el 7 de oros (también llamado el velo). Se procederá a anotar la puntuación de esa mano y a sumar las puntuaciones de las demás manos jugadas. Dependiendo de las reglas con las que se juegue, en caso de que dos jugadores empaten en el máximo número de cartas, oros o sietes, o bien no se concede el punto a nadie, o bien se le da un punto a cada jugador del empate. g.drawString("Hola mundo", 50, 25); } } Figura 1. Ejecución del applet en Firefox sobre Windows Gana el jugador que en sucesivas manos llega antes a conseguir los puntos fijados al principio de la partida (normalmente 21). 2.EL JUEGO DE LA ESCOBA Para la realización de este proyecto se ha creado un applet java que incluye la lógica de juego de la escoba. 2.1 Applets java Los applets pueden utilizar cualquier tipo de objetos, incluidos los objetos de awt o java swing. En particular un applet puede crear botones, ventanas independientes, canvas para despliegue general, etc. Lo que no puede hacer un applet es acceder a archivos o abrir conexiones con cualquier computador en la red. Sólo puede abrir conexiones con el computador desde donde se recuperó el applet. Un applet se crea extendiendo la clase Applet, que a su vez es una subclase de Panel. Un applet se distingue porque posee los siguientes métodos: •init(): Se invoca cuando se carga el applet y se usa para inicializar el applet. •start(): Se invoca cada vez que el usuario visita la página Web. El applet permanece cargado. •stop(): Se invoca cuando el usuario abandona la página Web. Si el usuario revisita la página y el applet todavía esta cargado, entonces se invocará start (sin init). Los applets java normalmente se incluyen en páginas web y se ejecutan mediante la máquina virtual de java. Para incorporar un applet en una pagina web sólo hay que usar usando las siguientes instrucciones html: <applet codebase=examples code=GuiApplet.class width=550 height=200> ... (parámetros) </applet> •destroy(): Se invoca justo antes de que el navegador Web destruya el applet. Sirve para cerrar archivos, cerrar conexiones y realizar otras labores. No es necesario liberar objetos porque el recolector de basura sabe hacerlo. En donde: •String getParameter(String nombre): se usa para recuperar parámetros que se espeficican en la página Web en donde se ubica el applet. •code: es el nombre del archivo que contiene el bytecode de la clase ya compilada. •codebase: es el directorio que contiene la clase del applet. En este caso el directorio es relativo al directorio en donde se encuentra la página Web. •width y height: es el tamaño del rectángulo que ocupará el applet en la página Web. Figura 3. Cartas del jugador humano (recuadradas en rojo) Entre las etiquetas applet y /applet se pueden colocar parámetros para el applet con: <param name=UNARGUMENTO value="valor"> Estos parámetros se reciben en el applet con: String arg= miApplet.getParameter("UNARGUMENTO"); En nuestro caso el código de invocación del applet es el siguiente: <APPLET CODE="Escoba.class" WIDTH=100% HEIGHT=100% alt="El explorador ve el applet pero no funciona"> El explorador esta ignorando el applet!!! </APPLET> Por alguna razón, el applet propuesto no funciona bajo Linux. Aunque en teoría, al ejecutarse dentro de una máquina virtual de java, debería ser multiplataforma sin necesidad ningún tipo de cambio, en la practica esto no es así. Por este motivo se ha incluido un código oculto que solo se muestra cuando el explorador ve el applet pero por algún motivo no lo ejecuta. Figura 2.Ejecución del applet en Konqueror sobre Linux Las cartas del jugador humano se encuentran en la parte inferior de la pantalla. Serán las que el jugador utilice para puntuar, al hacerlo una animación se llevará las cartas fuera de la pantalla. Para utilizar las cartas de la mano correctamente éstas son las últimas que deben ser seleccionadas. Para sumar 15, primero se seleccionan las cartas de la mesa que se quieren utilizar, en ese momento aparecerán recuadradas en amarillo, por último, se seleccionará las cara de la mano con la que se desee sumar 15. Figura 4. Cartas del jugador del ordenador (recuadradas en rojo) 2.2 Estructura del juego El juego, como todos los programas en java está estructurado en una serie de clases. La clase principal es Escoba, donde se cargan todos los recursos del juego incluidas las imágenes de las cartas, situadas en la carpeta mazo. Una vez cargados es la clase Juego la que se encarga de ir controlando el juego. En esta clase también se incluye la parte del código que toma las decisiones del jugador controlado por el ordenador. La zona de juego está repartida en 4 zonas claramente definidas: Las cartas del jugador controlado por el ordenador se encuentran en la parte superior de la pantalla. De la misma forma que en el caso del jugador humano, al puntuar una animación se llevará las cartas fuera de la pantalla. Durante la mayor parte de la partida las cartas del ordenador estarán ocultas, de hecho, solo se descubren cuando el jugador controlado por el ordenador utiliza una carta para sumar 15. Figura 5. Cartas en la mesa (recuadradas en rojo) directamente el numero de escobas que ha conseguido a lo largo del juego. Al contrario que el resto de las puntuaciones que se calculan al final, las escobas que se consiguen durante el juego, puntúan inmediatamente después de conseguirse. 2.3 Funcionamiento El funcionamiento del juego es muy sencillo, el jugador debe seleccionar primero las cartas de la mesa con las puede sumar 15 y acto seguido seleccionar la carta de su mazo con la que quiere hacerlo. Si efectivamente la combinación suma 15 las cartas se retiraran y se sumarán a los puntos del jugador. Figura 7. La selección de cartas Las cartas de la mesa son las que utilizarán ambos jugadores para sumar 15. en el caso del jugador controlado por el ordenador, esto se hace de forma totalmente automática ya que las cartas no se seleccionan sino que el ordenador pasa a retirarlas directamente. En el caso de jugador jugador humano, este selecionará las cartas de la mesa, que pasarán a estar recuadradas en amarillo para posteriormente seleccionar las carta de su mano con la que quiere hacer escoba. Figura 6. Marcador Como ya se ha mencionado, durante el juego solo se lleva la puntuación de las escobas, y al final de la partida se recuentan las cartas y se calcula la puntuación final. Es muy importante no realizar este proceso a la inversa. En las pruebas que se han realizado ha sido bastante común que el jugador tienda a seleccionar primero la carta de su mano que quiere usar y después las cartas de la mesa con las que quiere sumar 15. 3.PROBLEMAS ENCONTRADOS 3.1 Incompatibilidades con Linux En esta figura se muestra el final de del juego. Al final del juego se hace un recuento total de las escobas. En en el marcador, situado a la derecha se indica la puntuación de cada jugador de la siguiente manera. En el apartado de cartas se muestra el numero de cartas que ha obtenido cada jugador, el jugador que obtenga más cartas obtendrá una escoba. En total hay 40 cartas. En el apartado velos se indicará que jugador a conseguido el 7 de oros. Aquel que lo haya conseguido obtendrá una escoba. En el apartado oros se indican los oros obtenido por cada jugador. En total hay 10 oros en el juego, el que obtenga más oros obtendrá una escoba. En el caso de los sietes, se indica con 1 uno el jugador que ha obtenido más sietes, jugador que obtendrá una escoba. El caso de las escobas es diferente. en el se contarán Una de las dificultades que se han encontrado a la hora de desarrollar es la falta de compatibilidad con plataformas diferentes a Windows, ver figura 2. Aunque en principio la maquina virtual debería abstraer al applet la plataforma, en realidad no ocurre. Por ello, al cargar el applet, aunque el navegador no da ningún tipo de error no llega a crear la ventana del applet. 3.2 Fenómeno del doble buffer Otro de los problemas a los que ha habido que enfrentarse es el fenómeno conocido como doble buffer o double-buffering. Al mostrar gráficos con las técnicas estándar, las imágenes suelen aparecer a trozos o con parpadeo al irse dibujando secuencialmente en la pantalla. Las aplicaciones Java permiten que los programas dibujen en memoria, para luego ir mostrando la imagen completa de forma suave. Este es el proceso conocido como doble-buffering, y tiene dos ventajas fundamentales sobre el proceso normal de pintar o dibujar directamente sobre la pantalla: Primero, el usuario ve aparecer de golpe la imagen en la pantalla. Mientras el usuario está viendo esa imagen, el programa está generando la siguiente para mostrarla de golpe a continuación, y así una y otra vez. Segundo, la técnica de doble-buffering involucra un objeto Image, que se puede pasar directamente a varios métodos. Esta capacidad para manipular objetos Image permite descomponer las rutinas de dibujo en componentes funcionales, en lugar de un enorme método paint(). No obstante, el doble-buffering sólo debe usarse para animaciones gráficas, no como método normal. Lo usual en otras aplicaciones sería repintar la zona que interese solamente. Sin embargo a la hora de realizar las animaciones incluso utilizando el método paint(), ha sido imposible eliminando el parpadeo en las animaciones en las que se arrastran cartas. Sin embargo, si en vez de fondo verde oscuro, se utiliza un fondo negro, este parpadeo desaparece. Todavía no se ha encontrado una explicación a este fenómeno. 4.La inteligencia artificial Como corresponde a un trabajo de esta asignatura, a la hora de realizar el diseño se tuvo como una factor fundamental que el jugador del ordenador tuviera una inteligencia artificial creíble. Para ello se ideo un sistema más o menos complejo para que el jugador controlado por el ordenador tomara su decisiones. Este sistema tenía en cuenta las cartas que habían sido lanzadas por lo jugadores y estaban en los mazos de puntos así como las cartas que el jugador controlado por el ordenador tenia en la mano, para hacer una predicción de las posibles cartas del jugador humano, así elegir la mejor jugada teniendo en cuenta las posibles replicas. A la hora de implementar dicho sistema de inteligencia artificial se decidió hacer la implementación en dos fases. En la primera, el jugador controlado por el ordenador elegiría su mejor jugada y en la segunda fase, ademas, comprobaría las posibles replicas, llegando a una solución de compromiso entre la mejor jugada propia y la peor replica del contrario. Era de esperar, que sobre todo en las ultimas manos, al haber pocas cartas en el mazo, el jugador controlado por el ordenador fuera capaz de predecir con cierta precisión las cartas del contrario. A la hora de la verdad, solo se llegó a implementar la primera fase por un motivo fundamental, al realizar las pruebas con este modelo se comprobó no solo que el sistema funcionaba, sino que funcionaba muy bien y se acercaba enormemente a la forma de pensar de un jugador humano, que no es capaz de memorizar todas las cartas de la mesa. En resumen, el jugador controlado por el ordenador no solo era capaz de jugar razonablemente bien, sino que ganaba al jugador humano la mayoría de las veces dejando el destino de la partida en manos del azar. Esto es debido a que el jugador controlado por el ordenador piensa de la misma forma que un jugador humano, es decir, la jugada inmediata, y sin embargo, nunca comente errores. Esta paridad de pensamiento permite que las cartas que le aparecen a ambos jugadores ayuden a uno o a otro, permitiendo un juego equilibrado. Si con este sistema tan poco depurado, el nivel de dificultad ya es bastante aceptable, se pensó que implementar la segunda fase solo conseguiría que el jugador humano perdiera todas las manos, haciendo que el juego resultara aburrido. 4.1 Fase 1: Decisiones tomadas sobre datos conocidos. En la primera fase, el objetivo fundamental es que el ordenador sea capaz, a partir de sus cartas y de las cartas de la mesa, sea capaz de elegir la jugada que más le conviene. Como se ha visto en el apartado de reglamento, al finalizar el juego el jugador que gana es aquel que posee más escobas. El objetivo es seleccionar las jugadas que puntúen como una escoba o que me den más oportunidad de hacerlo. En principio, para el sistema de inteligencia artificial se diseño un sistema de puntuaciones. Una jugada de 1 punto era aquella que puntuaba como una escoba, una jugada de 0,3 es aquella que me da el tercio de una escoba, por ejemplo una jugada que involucre 2 oros. Con 6 oros nos aseguramos una escoba, porque en el mazo solo hay 10 y es imposible que nadie tenga más de 4. Una jugada con un el 7 de oros implica forzosamente una jugada con más de un punto ya que solo por tener el 7 de oros conseguimos una escoba más las caras que nos llevemos. Este sistema de debe depurar un poco, por ejemplo es mejor una jugada con el 7 de oros que hacer escoba con otra carta porque, aunque con la escoba te lleves más cartas, el 7 de oros si no puedes sumar 15 tienes que tirarlo, ofreciéndole una escoba en bandeja al contrario. 4.2 Fase2: Decisiones tomadas sobre datos estadísticos El sistema de puntuaciones se puede extender al jugador contrario utilizando un sistema básico de probabilidades. Si el jugador controlado por el ordenador tiene una probabilidad de un 30% de tener una carta con la que hacer escoba, le daremos una puntuación de 0.3. De esta forma podemos comparar nuestras jugadas con las del contrario, aunque como se explico anteriormente este sistema no se llego a implementar. Utilizando este sistema el jugador controlado por el ordenador puede ademas de realizar las mejores jugadas para el entorpecer al jugador humano, reduciendo sus posibilidades de puntuar. Los casos más claros se producen cuando puedes hacer una jugada que deje cartas en la mesa con una valor menor que 5 o una combinación para la que se necesite una cartas que ya han salido. 4.3 Sistema de toma de decisiones implementado El sistema de tomas de decisiones esta implementado en la clase Juego en el método cpuElegirCartas(). Para comenzar el ordenador comprueba que en la mesa hay cartas, en el caso de que esto no sea así será imposible hacer una escoba, y la CPU intentara lanzar una carta con un valor inferior a cinco para que el contrario tampoco pueda hacer escoba en su turno. El siguiente paso es comprobar el 7 de oros está en la mano. Teniendo en cuenta que el 7 de oros puntúa como una escoba, es importante utilizarlo cuanto antes, para minimizar la posibilidad de tener que tirarlo sin poder sumar 15 y que se lo quede el contrario. Una ves que se ha comprobado que es posible hacer escoba y que el 7 de oros no está en la mano se pasa a buscar una escoba en concreto. Para ello se utiliza el típico algoritmo de búsqueda en profundidad, comprobando para cada carta de nuestra mano si podemos sumar 15 con las cartas de la mesa. Si no se puede sumar 15 con ninguna de las cartas de la mesa, el ordenador seleccionará una carta al azar para lanzar. 5.Lineas futuras Como en cualquier proyecto ha habido alguna carteristas que no se han añadido al juego principalmente por falta de tiempo y para prevenir errores. El primer caso, ya explicado, es el de la inteligencia artificial. Sería interesante que el juego contase con diferentes niveles de dificultad para adaptarse mejor a cada jugador, desde el jugador casual, hasta el experto en el juego de la escoba. En el nivel más fácil se podría incluir la posibilidad de que el jugador controlado por el ordenador no sumase 15 siempre que pudiese. De la misma forma en el nivel más difícil se implementaría la segunda segunda fase de inteligencia artificial propuesta.. Además se podría seleccionar la carta aleatoria, en caso de no poder sumar 15, según algunos criterios, como por ejemplo intentar no seleccionar los 7 o los oros. Otra factor que se podría mejorar es el de las animaciones. Aunque se ha intentado utilizar la técnica de doble buffer a la hora de realizar las animaciones, ha sido imposible evitar el efecto parpadeo. De esta forma, cuando las cartas se deslizan por la pantalla a aparece un efecto de parpadeo al moverse. Otra idea que se podría implementar fácilmente es pasar de realizar el conteo de los punto a hacerlo durante la duración de juego. Aunque en el juego se cuentan escobas, por ejemplo se podría contar también el 7 de oros que cuenta como una escoba asegurada, o dale la escoba de los oros al primer jugador que tenga 6 oros, sin necesidad de esperar a terminar la partida, etc. 6. Conclusiones Durante el transcurso de este trabajo se han llegado a algunas conclusiones interesantes. La principal conclusión a la que podemos llegar después de la realización del trabajo es que no es necesario implementar un sistema de toma de decisiones demasiado complicado para conseguir un jugador controlado por el ordenador se comporte de una forma realista. La segunda conclusión a la que podemos llegar es que aunque el juego se realice como applet en java es necesario prestar atención a su portabilidad. Aunque en teoría la máquina virtual de java debería abstraer al programador de todo lo referente a portabilidad, en la realidad nos podemos encontrar con que si no se presta atención al código en cada fase del desarrollo y se va probando en diferentes plataformas, se puede dar el caso de que el applet presente incompatibilidades con algunos sistemas operativos, y al encontrarse en una fase avanzada del desarrollo sea difícil corregir el código para evitarlo. Para finalizar, simplemente resaltar que mediante java AWT y java Swing es posible realizar aplicaciones gráficas sencillas sin necesidad de unos conocimientos de programación avanzados, aunque para conseguir unos buenos resultados es necesario tener cuidado y solventar desde el principios posibles problemas como el del doble-buffer. 7. Bibliografía [1]Wikipedia, página sobre la escoba. DOI= http://es.wikipedia.org/wiki/Escoba_del_15 [2]http://eddi.ith.mx/Curso/Contenido/Applets.htm