Academia.eduAcademia.edu

Implementación de un juego de mus en red sobre SIP

2008

View metadata, citation and similar papers at core.ac.uk brought to you by CORE provided by UPCommons. Portal del coneixement obert de la UPC TRABAJO FIN DE CARRERA TÍTULO DEL TFC: Implementación de un juego de mus en red sobre SIP TITULACIÓN: Ingeniería Técnica de Telecomunicaciones, especialidad Telemática AUTORES: Ignacio Ginés Fernández Héctor Maestro Alegre DIRECTOR: Sergio Machado FECHA: 11 de julio de 2008 Título: Implementación de un juego de mus en red sobre SIP Autores: Ignacio Ginés Fernández Héctor Maestro Alegre Director: Sergio Machado Fecha: 11 de julio de 2008 Resumen El objetivo de este proyecto es crear un sistema para jugar al mus en red utilizando SIP como protocolo de señalización, y donde los usuarios podrán jugar partidas contra otros o contra un motor de inteligencia artificial. El sistema dispone de un servidor central donde los usuarios se conectan, y sirve de nexo entre ellos para unirse y jugar partidas. El proyecto también ha de permitir jugar a un jugador solo contra un motor de inteligencia artificial, creado en un TFC paralelo, realizado por otros compañeros y utilizado en éste. Tanto la aplicación cliente, como la del servidor, han sido programadas en Java. Se ha usado JAIN-SIP como implementación de SIP, una librería que define métodos y clases para poder utilizar el protocolo. Se ha realizado un estudio teórico del protocolo para poder implementar un servidor y un cliente propio. La aplicación cliente tiene una interfaz gráfica diseñada en SWT, una librería de Java que utiliza los componentes nativos del sistema operativo. La interfaz está estructurada en tres paneles, según la función de cada uno: sala de conexión, sala de partidas y el tapete de juego. El servidor central ha de controlar la creación de partidas y la presencia de los usuarios, permitiendo que éstos conozcan quién está conectado y dándoles la posibilidad de crear una lista privada con sus amigos. El servidor también ofrece a los usuarios un chat para comunicarse. Una vez empieza la partida, se crea un motor de juego, que realiza las funciones de servidor de la partida. Durante la partida, el servidor central sigue manteniendo el control de presencia, y si un jugador abandona, ha de añadir un motor de inteligencia artificial que continúe la partida por él. Asimismo, si este jugador vuelve a conectarse el servidor le da la opción de retornar a la partida. Title: Implementation of a mus online game on SIP Authors: Ignacio Ginés Fernández Héctor Maestro Alegre Director: Sergio Machado Date: July, 11th 2008 Overview The objective of this project is the design and implementation of a system for playing online mus, a Spanish card game, using SIP as a signaling protocol and where users can play games against other human players or against an artificial intelligence engine. The system relies on a central server where users log in for playing and which provides a presence service. Client and server applications have been programmed with Java. The SIP implementation for Java used has been JAIN-SIP, a collection of libraries that define an API to use SIP in Java applications. The user interface has been developed with SWT, a Java graphic library that uses the operative system native widgets. The interface is structured in three panels according to their own functionality: connection room, waiting room and playing room. Central server must control the creation of games and the presence of the users in the system, allowing them to take knowledge of who is also connected in the system and providing them the possibility to have a private friends list. In order to facilitate the intercommunication of the users, the server also provides a chat service. Once a game is started, the application relies on a game engine which acts as a game-server and which is independent of the central server, which only takes care of presence control, and when a player leaves the game, it informs to the game-server that it must instantiate an AI engine for replacing the human player. In the same way, if the player reconnects to the central server, it can help the user to rejoin the game. "El destino reparte las cartas, pero somos nosotros los que las jugamos" Arthur Schopenhauer ÍNDICE INTRODUCCIÓN ............................................................................................... 1 CAPÍTULO 1. ARQUITECTURA ....................................................................... 3 1.1. Esquema general ....................................................................................................... 3 1.1.1. Aplicación del cliente........................................................................................... 4 1.1.2. Servidor central ................................................................................................... 4 1.1.3. Motor de juego .................................................................................................... 4 1.2. SIP ............................................................................................................................... 5 1.2.1. Introducción ......................................................................................................... 5 1.2.1. Mensajes SIP ...................................................................................................... 5 1.3. JAIN-SIP .................................................................................................................... 10 1.4. JSON ......................................................................................................................... 12 CAPÍTULO 2. APLICACIÓN DE USUARIO .................................................... 15 2.1. Introducción ............................................................................................................. 15 2.2. Esquema de la aplicación ....................................................................................... 15 2.3. Jugar en local ........................................................................................................... 18 2.4. Interfaz gráfica.......................................................................................................... 19 2.4.1. SWT................................................................................................................... 19 2.4.2. Sala de inicio ..................................................................................................... 19 2.4.3. Sala de espera .................................................................................................. 20 2.4.4. Sala de juego .................................................................................................... 22 2.4.2. Barra Estado ..................................................................................................... 24 CAPÍTULO 3. SERVIDOR ÁGORA ................................................................. 25 3.1. Introducción ............................................................................................................. 25 3.2. Conexión al Ágora ................................................................................................... 25 3.3. Desconexión del Ágora ........................................................................................... 27 3.4. Presencia en el servidor.......................................................................................... 27 3.5. Información persistente .......................................................................................... 29 3.5.1. Base de datos ................................................................................................... 29 3.5.2. Registro en Ágora ............................................................................................. 30 3.5.3. Lista de amigos ................................................................................................. 31 3.6. Control de partidas .................................................................................................. 34 3.6.1. Clase datos ....................................................................................................... 35 3.6.2. Creación de la partida ....................................................................................... 36 3.6.3. Estado esperando ............................................................................................. 36 3.6.4. Empezar la partida ............................................................................................ 38 3.7. Mensajería................................................................................................................. 39 3.7.1. Funcionalidades del servidor ............................................................................ 39 3.7.2. Crear, unirse y salir de una partida ................................................................... 40 3.7.3. Introducir jugador en una partida iniciada ......................................................... 41 3.7.4. Gestión de la lista de amigos ............................................................................ 42 CAPÍTULO 4. MOTOR DE JUEGO ................................................................. 45 4.1. Introducción ............................................................................................................. 45 4.2. Esquema del motor de juego.................................................................................. 45 4.2.1. Inicio de la partida ............................................................................................. 46 4.2.2. Fin de la partida................................................................................................. 47 4.3. El juego del mus....................................................................................................... 47 4.3.1. Lances del juego ............................................................................................... 48 4.3.2. Fase mus........................................................................................................... 49 4.3.3. Fase de apuestas.............................................................................................. 50 4.3.4. Fase de recuento de piedras ............................................................................ 53 CAPÍTULO 5. INTERACCIÓN CON LA INTELIGENCIA ARTIFICIAL ........... 55 5.1. Introducción ............................................................................................................. 55 5.2. Estado de la partida ................................................................................................. 55 5.3. Introducir un jugador............................................................................................... 56 5.3.1. Introducir IA ....................................................................................................... 57 5.3.2. Retorno jugador humano................................................................................... 58 CAPÍTULO 6. CONCLUSIONES ..................................................................... 61 6.1 Ambientalización...................................................................................................... 62 6.2 Agradecimientos ...................................................................................................... 62 BIBLIOGRAFÍA ............................................................................................... 63 ÍNDICE DE FIGURAS Fig. 1.1 Esquema general del juego de mus desarrollado............................................................ 3 Fig. 1.2 Captura de un mensaje SIP ............................................................................................. 6 Fig. 1.3 Intercambio de mensajes para crear un diálogo .............................................................. 9 Fig. 1.4 Intercambio de mensajes para suscribirse a un evento................................................... 9 Fig. 1.5 Elementos necesarios de una SIPStack ........................................................................ 10 Fig. 1.6 Estructura de capas de SIP dentro de la aplicación ...................................................... 11 Fig. 1.7 Ejemplo de una clase serializada en formato JSON...................................................... 13 Fig. 2.1 Diagrama de clases de la aplicación de usuario............................................................ 17 Fig. 2.2 Diagrama de clases del motor de inteligencia artificial .................................................. 17 Fig. 2.3 Proceso de creación de objetos nuevos ........................................................................ 18 Fig. 2.4 Conexión al servidor....................................................................................................... 19 Fig. 2.5 Juego con IA .................................................................................................................. 20 Fig. 2.6 Sala de Espera............................................................................................................... 20 Fig. 2.7 Lista de amigos .............................................................................................................. 21 Fig. 2.8 Menú del ratón ............................................................................................................... 21 Fig. 2.9 Zona de partidas de la sala de espera........................................................................... 22 Fig. 2.10 Tapete de juego ........................................................................................................... 23 Fig. 2.11 Información de la partida.............................................................................................. 23 Fig. 2.12 Ventana de resultado final de mano ............................................................................ 24 Fig. 3.1 Intercambio inicial de mensajes ..................................................................................... 26 Fig. 3.2 Protocolo de mensajes para el control de presencia ..................................................... 28 Fig. 3.3 Modelo E-R de la tabla jugador y la de amigo ............................................................... 29 Fig. 3.4 Ejemplo de lista de amigos ............................................................................................ 31 Fig. 3.5 Diagrama de flujo para añadir un nuevo amigo ............................................................. 32 Fig. 3.6 Protocolo de mensajes para añadir nuevo amigo.......................................................... 33 Fig. 3.7 Diagrama de flujo para eliminar un amigo ..................................................................... 34 Fig. 3.8 Esquema de la clase datos ............................................................................................ 35 Fig. 3.9 Protocolo de mensajes de invitar a la partida ................................................................ 37 Fig. 3.10 Diagrama del estado de espera de la partida .............................................................. 38 Fig. 3.11 Estructura general del mensaje ................................................................................... 39 Fig. 4.1 Arquitectura de la partida ............................................................................................... 45 Fig. 4.2 Diagrama de clases del motor de juego......................................................................... 46 Fig. 4.3 Diagrama de flujo de la fase mus................................................................................... 50 Fig. 4.4 Diagrama de flujo de las apuestas ................................................................................. 51 Fig. 4.5 Diagrama de flujo del envite........................................................................................... 52 Fig. 4.6 Diagrama de flujo del órdago ......................................................................................... 53 Fig. 4.7 Diagrama del recuento de puntos .................................................................................. 54 Fig. 5.1. Clase EstadoPartida...................................................................................................... 56 Fig. 5.2. Intercambio de mensajes para introducir una IA .......................................................... 57 Fig. 5.3. Intercambio de mensajes para meter a un jugador caído............................................. 58 INTRODUCCIÓN 1 INTRODUCCIÓN El objetivo que se persigue en este proyecto es el de crear un sistema para jugar al mus en red para varios jugadores, donde puedan jugar contra otros y/o contra un motor de inteligencia artificial. El sistema dispone de un control de presencia para conocer el estado de los usuarios. El lenguaje de programación utilizado es Java y el protocolo de comunicación es SIP, que permite establecer sesiones entre usuarios y la señalización de eventos. Para conectar a los jugadores de la partida se ha implementado un servidor SIP que gestiona la conexión y la presencia de usuarios, además de la creación de partidas y la unión de jugadores a ellas. Otro servicio que ofrece es el de crear una lista privada de amigos para cada usuario. Los datos persistentes, como los nombres o las listas de amigos, se almacenan en una base de datos del servidor. Se ha creado una aplicación del lado del usuario con interfaz gráfica. Interfaz diseñada en SWT y estructurada en tres paneles, uno inicial para elegir las opciones de conexión, otro para mostrar los jugadores y partidas del servidor, y un último panel donde se juega la partida. Además de conectarse a un servidor, conociendo su dirección IP y puerto, la aplicación cliente permite jugar partidas en local. En este caso, el usuario creará tres motores de inteligencia artificial, diseñados en un proyecto paralelo a éste. En el primer capítulo se define la arquitectura utilizada para implementar el juego en red. También se especifican las tecnologías utilizadas: el protocolo SIP y su implementación en Java, JAIN-SIP; y el formato para serializar los datos JSON y su implementación XStream. En el segundo capítulo se explica la aplicación de usuario implementada en SWT, como está estructurada y un manual de la interfaz gráfica. En el tercer capítulo se describe el servidor implementado. En él se detalla cómo se conectan los usuarios al servidor mediante diálogos SIP, la suscripción a eventos y el control de presencia que éste mantiene con los usuarios. También se explica cómo el servidor controla la creación y el estado de las partidas y cómo almacena los datos persistentes de los usuarios. En el cuarto capítulo, dedicado al motor de juego, se detalla cómo y cuando se ha de crear, la arquitectura de éste y el motor que controla el flujo de la partida. Además se incluye una explicación del juego del mus y sus reglas. En el quinto y último capítulo se explica la interacción con el motor de inteligencia artificial, detallando cómo se introduce en mitad de una partida iniciada cuando un jugador se desconecta. También de describe el proceso de retorno de un jugador en la partida. CAPÍTULO 1. Arquitectura 3 CAPÍTULO 1. Arquitectura 1.1. Esquema general El objetivo del proyecto es crear un sistema que permita jugar al mus tanto individualmente, jugando con motores de inteligencia artificial, como en red, jugando con humanos y/o inteligencia artificial. El sistema consta de la aplicación del cliente, con interfaz gráfica, y el servidor que hace de punto central de gestión de partidas, presencia de jugadores y almacenamiento de información. Además la aplicación permite jugar partidas contra un motor de inteligencia artificial creado en otro proyecto. El proyecto se ha programado en lenguaje Java y el protocolo de comunicación utilizado es SIP [1] (Session Initiation Protocol). Este protocolo ofrece, a través de los diálogos y la suscripción a eventos, una forma sencilla de crear y finalizar sesiones, controlar la presencia de jugadores y distribuir la información a todos ellos. La figura 1.1 muestra la arquitectura del proyecto. El servidor es el punto central del sistema, y almacena de forma persistente la información de los usuarios registrados en una base de datos. Los usuarios se conectan a él para jugar partidas en red, estableciendo diálogos SIP para el control de presencia. Cuando se inicia la partida, un usuario es el encargado de crear el motor de juego. Este motor es el encargado de gestionar toda la partida, el servidor central no interviene en su transcurso. Fig. 1.1 Esquema general del juego de mus desarrollado 4 Implementación de un juego de mus en red sobre SIP 1.1.1. Aplicación del cliente Se ha creado una aplicación para el usuario con interfaz gráfica, implementada en SWT [7] (Standard Widget Toolkit). Esta aplicación permite conectarse al servidor central a través de su dirección IP. Una vez conectado, puede crear partidas online en el servidor para jugar con otros usuarios. También puede gestionar una lista de amigos, única por cada usuario, y comprobar si estos están conectados o no. Por último, ofrece la posibilidad de jugar una partida en local contra un motor de inteligencia artificial. 1.1.2. Servidor central Se ha implementado el servidor donde los usuarios se conectan para jugar partidas en red. Es un nodo central que une a los usuarios y les permite ver si hay otros conectados. Gestiona las partidas en juego, aceptando a usuarios que quieran jugar en ella, controlando durante la partida que todos estén conectados y si no es así introduce un motor de inteligencia artificial. También guarda de forma persistente la información de cada usuario registrado, contraseña y lista de amigos, en una base de datos. Así un usuario puede conectarse desde cualquier lugar y dispone de toda su información. 1.1.3. Motor de juego El servidor central sirve como punto de encuentro para los jugadores. Una vez empieza la partida la comunicación ya no pasa por él, sino que va directamente entre los jugadores de la partida y el motor de juego. Cuando el servidor central detecta que en una partida hay cuatro jugadores (los jugadores reales y la inteligencia artificial son tratados indistintamente como jugadores de la partida) se envía la información necesaria al creador de la partida y éste adopta el papel de servidor de la partida, creando un motor de juego de la partida de mus. El creador es el usuario que ha definido los parámetros de la partida, si éste se desconecta mientras se espera a más jugadores, el creador pasa a ser el segundo jugador en unirse a la partida, y así sucesivamente. El motor gestiona el flujo de una partida de mus: es el encargado de hacer las peticiones a los jugadores dentro de cada fase del juego, en el orden adecuado; resolver las jugadas; llevar el control de las puntuaciones y determinar los ganadores. Toda esta comunicación entre los jugadores de la partida y el motor de juego se realiza sobre SIP, aprovechando la estructura SIP que tienen los clientes con el servidor central. CAPÍTULO 1. Arquitectura 5 1.2. SIP 1.2.1. Introducción SIP es un protocolo de la capa de aplicación desarrollado por el IETF [13] y definido en su última versión en el RFC 3261 [1]. Se utiliza habitualmente en aplicaciones multimedia de voz, juegos online y mensajería instantánea. Se encarga de la señalización de las sesiones, su creación, modificación y finalización. Los elementos que se definen dentro del protocolo son los siguientes: • Agente Usuario: punto extremo de la sesión, es el encargado de iniciarla y el receptor de toda la información que se produzca en ella. SIP sigue una estructura cliente-servidor en el intercambio de mensajes, se distingue entre UAC (User Agents Clients) y UAS (User Agents Servers). El cliente realiza una petición (request) y el servidor contesta con una respuesta (response), a este intercambio se le llama transacción. En nuestro proyecto este papel lo desempeñan tanto la aplicación de usuario como el servidor central. • Servidores de Registro: encargados de asociar la dirección lógica de un usuario (única y de formato a “sip: user@hostname”) con su dirección física (variable). La dirección lógica permite identificar a un usuario sin tener en cuenta su ubicación, esta es una de las ventajas que ofrece SIP. • Servidores Proxy: son los encargados de encaminar los mensajes entre los diferentes UA, realizan únicamente la función de punto intermedio. En el proyecto se ha optado por diseñar un servidor propio con todas las funciones necesarias para el juego de mus en red. SIP cumple la función de creación y finalización de las sesiones entre el jugador y el servidor central, la notificación de eventos y el control de presencia de usuarios. 1.2.1. Mensajes SIP En este apartado se explica como están formados los mensajes SIP, sus cabeceras y los diferentes tipos. También se explican en detalle los mensajes utilizados en el proyecto, así como los conceptos de diálogo SIP y suscripción a eventos. 6 Implementación de un juego de mus en red sobre SIP 1.2.1.1. Cabeceras Todos los mensajes SIP tienen unas cabeceras mínimas que hay que incluir tanto en las peticiones como en las respuestas. En la figura 1.2 se muestra una captura de la cabecera de un mensaje INVITE que servirá para explicar los campos que la componen: Fig. 1.2 Captura de un mensaje SIP 1ª Línea: método / URI1 / SIP version Cabeceras: • Call-Id: identificador único de la conversación entre dos UA • CSeq: número de secuencia de la petición • From: origen de la petición • To: destino de la petición • Via: SIP version / transport protocol, owner@host, branchId • Contact: nombre / URI de origen • Content-Type: tipo de datos del contenido del mensaje • Content-Length: tamaño del contenido del mensaje Después de la cabecera se encuentra una línea en blanco que marca el final y el inicio del contenido o cuerpo del mensaje. 1 URI (Uniform Resource Identifier) : cadena de caracteres que identifica inequívocamente a un recurso, en nuestro proyecto a una pila SIP. CAPÍTULO 1. Arquitectura 1.2.1.2. 7 Peticiones El mensaje que envía un UAC se llama petición. Cada petición está definida por el campo método de la primera línea de la cabecera. Hay seis métodos básicos definidos en el RFC 3261 [1] con los que crear, modificar y finalizar las sesiones SIP: INVITE, ACK, BYE, CANCEL, REGISTER y OPTIONS. En el proyecto hemos utilizado los RFC 4579 [2] y 2822 [3] que definen el uso de métodos adicionales: MESSAGE, SUBSCRIBE y NOTIFY. Estos métodos permiten implementar la suscripción a eventos y el envío de mensajes. Aquí se encuentran definidos los métodos obligatorios y los adicionales utilizados en el proyecto: • INVITE: sirve para establecer una sesión con un UAS o modificar los parámetros de una sesión ya existente. • ACK: confirma el establecimiento de una sesión. • BYE: indica la finalización de una sesión por parte de un UAC. • CANCEL: cancela una petición pendiente de respuesta, como por ejemplo una petición de diálogo. • REGISTER: para registrar un UA en un servidor de registro. • OPTIONS: solicita información sobre las capacidades de un servidor. • MESSAGE: mensaje dentro de una sesión. • SUSCRIBRE: es una petición de un nodo a otro para suscribirse a un evento, para conocer su estado y cambios. • NOTIFY: petición para informar a los nodos sucritos a un evento de cambios en él. 1.2.1.3. Respuestas SIP utiliza la estructura petición-respuesta manteniendo el estado de sesión. Las respuestas están clasificadas según códigos numéricos: • 1xx: respuestas informativa • 2xx: la petición ha sido recibida y aceptada • 3xx: la petición tiene que ser redireccionada, incluye información de la nueva dirección 8 Implementación de un juego de mus en red sobre SIP • 4xx: error de petición, no tiene formato o contenido válido, es necesario reconstruir una nueva petición modificada • 5xx: error de servidor, el servidor ha fallado con una petición válida • 6xx: error global Los códigos de respuesta dan claridad a la hora de interpretar el error ocurrido. Como se puede observar SIP es un protocolo simple y claro de utilizar. En el RFC 3261 [1] se definen los mensajes que cualquier aplicación SIP tiene que implementar obligatoriamente, para así poder interconectar diferentes aplicaciones. Para el proyecto se ha hecho uso de dos conceptos de SIP: diálogo y suscripción a eventos. A continuación se explican de forma general los dos conceptos. 1.2.1.4. Diálogos Los mensajes entre dos UA pueden intercambiarse de dos formas diferentes: dentro de un dialogo o como mensajes independientes. Si se envía como un mensaje independiente, SIP se comporta como un simple protocolo para el envío de información a nivel de aplicación. Cuando el UAC crea mensajes, ha de rellenar todos los campos obligatorios de la cabecera de cada mensaje, sin tener en cuenta las peticiones enviadas anteriormente o las que se vayan a enviar después, sólo ha de comprobar que la información referente al origen y al destino sea la correcta. Al enviar las peticiones de esta manera, SIP no las controla como parte de un flujo, así campos de la cabecera como CSeq no tienen ninguna utilidad ya que las peticiones no están ligadas entre si, ni forman parte de un diálogo. Si las peticiones se envían dentro de un diálogo, el UAC sólo se ha de encargar de rellenar las cabeceras del primer mensaje, fijando el valor de CSeq a un valor inicial conocido, por ejemplo 1. SIP se encarga de rellenar adecuadamente las cabeceras de los mensajes posteriores que forman parte del diálogo. De esta forma la implementación de SIP lleva un control de los mensajes y su estado para posibles retransmisiones, comprueba que las respuestas a las peticiones se reciban correctamente en un tiempo determinado, y si una petición no recibe respuesta salta un temporizador (timeoutEvent) que avisa de tal suceso y así se puede controlar. Para crear un diálogo entre dos UA el cliente envía un primer mensaje INVITE y el servidor contesta con una respuesta afirmativa, si es posible establecer el diálogo. Finalmente el cliente envía un mensaje ACK de confirmación. En la figura 1.3 se detalla el intercambio de mensajes. CAPÍTULO 1. Arquitectura 9 Fig. 1.3 Intercambio de mensajes para crear un diálogo 1.2.1.5. Suscripción a eventos La suscripción a eventos consiste en la petición que realiza un UAC al UAS para suscribirse a un evento concreto y así recibir los posibles cambios en él. El mensaje para suscribirse es SUBSCRIBE y la notificación de los cambios en el evento se hace mediante un mensaje NOTIFY. Todo el proceso de suscripción y notificación se ha implementado siguiendo las especificaciones del RFC 4579 [2] que define el intercambio de mensajes para la suscripción en una conferencia. En la figura 1.4 se muestra un ejemplo. Fig. 1.4 Intercambio de mensajes para suscribirse a un evento 10 Implementación de un juego de mus en red sobre SIP 1.3. JAIN-SIP La implementación de SIP que se ha utilizado es JAIN-SIP v1.2 [9], está desarrollado por el NIST [14] (Instituto Nacional de Normas y Tecnología de EEUU). Es un proyecto con un amplio soporte y una de las implementaciones más utilizadas en Java. JAIN-SIP es una especificación que soporta completamente el RFC 3261 [1], además de otras ampliaciones. Puede ser utilizada en aplicaciones como Agente de Usuario, Servidor Proxy y Servidor de Registro. Permite transacciones con estado, sin estado y un control de los diálogos. Posee diferentes paquetes y clases para crear todos los elementos necesarios para una pila SIP. En la figura 1.5 podemos ver un diagrama con los elementos mínimos que tiene la pila SIP (SIPStack): Fig. 1.5 Elementos necesarios de una SIPStack • SIPListener: interfaz que define los métodos para la crear un canal de comunicación SIP. • Propiedades: conjunto de parámetros que definen la pila SIP. La única propiedad obligatoria es el nombre de la pila SIP. CAPÍTULO 1. Arquitectura 11 • Factories: clases necesarias para la creación de diálogos, transacciones, peticiones, respuestas, inicializar los puertos de escucha, etc. • ListeningPoints y SIProvider: estos dos objetos dan las funcionalidades de comunicación para enviar y recibir mensajes. En la figura 1.6 se observa la estructura de capas y la posición que ocupa la SIPStack en ella. A continuación se detalla la función de cada capa. La aplicación de usuario se comunica con la pila SIP para enviar y recibir mensajes. Cualquier evento de la red le llega a la aplicación a través de la pila SIP. La SIPStack envía y recibe los mensajes interactuando con la capa de transporte, estos mensajes se pueden enviar dentro de un diálogo o como mensajes sueltos, como se ha explicado en la sección 1.2.1.4. Esta capa es la encargada de la creación de los mensajes, el control de su recepción, las retransmisiones a nivel de aplicación y la notificación de las excepciones si se produce algún error. La capa de transporte recibe los mensajes SIP y los envía utilizando el protocolo definido en las cabeceras, TCP o UDP. En nuestra aplicación hemos utilizado UDP como protocolo de transporte ya que añade menos información en sus cabeceras e introduce poco retardo. SIP ya se encarga de controlar la correcta recepción de los mensajes y el estado de la conexión. Por otro lado, UDP es el protocolo de transporte más utilizado y soportado en la mayoría de aplicaciones [15]. Fig. 1.6 Estructura de capas de SIP dentro de la aplicación 12 Implementación de un juego de mus en red sobre SIP 1.4. JSON JSON [10] (JavaScript Object Notation) es un formato de texto usado en la serialización de datos y está definido en el RFC 4627 [4]. JSON es similar a XML [6] ya que ambos sirven para el intercambio de información estructurada, con la ventaja de ser más ligero y fácil de interpretar que XML. Es una herramienta muy útil cuando se necesita estructurar información en un formato de marcas. El formato JSON permite estructurar diversos tipos de lenguajes de programación. Existen implementaciones para diferentes tipos como: C, C++, Java, JavaScript, Perl, Python, etc. JSON puede representar los siguientes tipos de datos: • Datos primitivos: numbers, booleans, null y strings. Un string es una secuencia de cero o más caracteres UNICODE. • Tipos de estructuras: - Object: colección no ordenada de cero o más pares “nombre/valor”, donde el nombre es un string y el valor puede ser un string, number, boolean, null, object o array. - Array: es una secuencia ordenada de cero o más valores. La implementación para Java que hemos utilizado es XStream [11]. Es una librería que permite serializar datos. Proporciona un paquete llamado JettisonMappedXMLDriver que transforma objetos Java y texto XML en formato JSON. Con esta implementación se puede convertir una clase Java a un string, y al revés, a partir de un string instanciar una clase. En nuestro proyecto se ha utilizado JSON para dar formato a los datos enviados dentro del mensaje NOTIFY, en él se envía toda la información que necesita la interfaz gráfica para actualizarse. CAPÍTULO 1. Arquitectura Fig. 1.7 Ejemplo de una clase serializada en formato JSON 13 CAPÍTULO 2. Aplicación de Usuario 15 CAPÍTULO 2. Aplicación de Usuario 2.1. Introducción En este capítulo se explica la aplicación de usuario, sus funciones, elementos y estructura. Si el servidor central es la parte del proyecto que ofrece la conexión entre usuarios, la aplicación es la encargada de interactuar directamente con el usuario. Interactúa con él mostrando en la interfaz gráfica toda la información que recibe del servidor, también envía las acciones realizadas por el usuario al servidor. La comunicación con el servidor se realiza mediante un diálogo SIP para el envío/recepción de mensajes. Hay que definir una estructura de clases que permita a la aplicación poder ser usada por un jugador y, cuando sea requerido, crear en ella el motor de juego de una partida y los motores de inteligencia artificial necesarios. También ofrece la posibilidad de jugar partidas en local, sin necesidad de estar conectado al servidor. La aplicación muestra toda la información al usuario a través de la interfaz gráfica, implementada en SWT. Al final del capítulo hay un pequeño manual de usuario. 2.2. Esquema de la aplicación La aplicación de usuario se conecta con el servidor central y establece con él un diálogo SIP, el intercambio de mensajes se explica en el capítulo 3 dedicado al servidor central. La interfaz gráfica dispone de tres paneles: • Sala de inicio: donde introducir los datos de conexión al servidor central. • Sala de espera: donde se pueden crear partidas, ver los jugadores conectados y la lista de amigos. • Sala de juego: donde se juegan las partidas de mus. La aplicación también ha de crear, si el usuario tiene el rol de creador de la partida, el motor de juego y los motores de inteligencia artificial necesarios. Tanto el motor de juego, que realiza la función de servidor de partida, como los motores de inteligencia artificial, realizan una comunicación por red durante la partida con los otros jugadores. Cada uno de estos objetos necesita una pila 16 Implementación de un juego de mus en red sobre SIP SIP para el envío/recepción de mensajes, estas pilas son creadas por la aplicación. Si es una partida en local, también hay comunicación por red entre los diferentes objetos. Esto es así para tratar a los diferentes modos de juego de la misma manera. Al diseñar la aplicación se ha tenido en cuenta esta circunstancia, y se ha creado un esquema de clases que permita a la aplicación crear nuevos objetos según se necesiten. A continuación está la explicación de cada clase, seguida de dos figuras con los diagramas de clases. En la figura 2.1 está el diagrama de la aplicación, y en la figura 2.2 se encuentra el diagrama de clases del motor de inteligencia artificial. • MusSWT: es la clase principal de la aplicación, la que contiene los paneles y componentes de la interfaz gráfica. También tiene un objeto de la clase MusJugador. Si se ha de crear algún tipo de motor de juego o de inteligencia artificial, se crearán en esta clase. • JugadorInterface: interfaz donde se definen los métodos de la partida para un jugador: fases, envites, acciones... Estos métodos son comunes tanto en el jugador humano como en el motor de inteligencia artificial. • MusJugador: clase que implementa JugadorInterface en ella se relacionan los métodos de la interfaz con los métodos propios de la interfaz gráfica. Se crea un objeto MusClient. • MotorIA: motor de inteligencia artificial que tiene un objeto de la clase MusJugadorIA • MusJugadorIA: clase que implementa JugadorInterface en ella se relacionan los métodos de la interfaz con los métodos del motor de inteligencia artificial. También crea un objeto MusClient. • MusClient: clase encargada de comunicar la pila SIP con el MusJugador. Es una clase intermedia que tienen tanto el jugador humano como el motor de inteligencia artificial. Es la encargada de crear la pila SIP. • MusSipClient: la pila SIP con los métodos propios para el envío y recepción de mensajes SIP. En cada aplicación sólo se crea un objeto MusJugador en el momento de establecer la conexión con servidor central. CAPÍTULO 2. Aplicación de Usuario Fig. 2.1 Diagrama de clases de la aplicación de usuario Fig. 2.2 Diagrama de clases del motor de inteligencia artificial 17 18 Implementación de un juego de mus en red sobre SIP Resumiendo, por defecto siempre se crea una pila SIP, correspondiente al jugador humano, utilizada tanto en la comunicación con el servidor central como dentro de la partida. Dependiendo de la situación, la aplicación puede llegar a tener diversas pilas SIP escuchando por diferentes puertos, correspondientes a los motores de inteligencia y al motor de juego de la partida. Hay que resaltar que el motor de juego y los motores de inteligencia artificial sólo se comunican entre ellos y dentro de una partida, nunca tienen comunicación alguna con el servidor central. Fig. 2.3 Proceso de creación de objetos nuevos 2.3. Jugar en local La aplicación de usuario también ofrece la posibilidad de jugar una partida sin conexión al servidor, una partida en local. En ella el usuario juega contra tres motores de inteligencia artificial. La aplicación creará todos los elementos necesarios para jugarla. Un usuario puede estar conectado al servidor y a la vez jugar una partida en local, únicamente no se permite estar en dos partidas a la vez, ya sea jugando o esperando a más jugadores. CAPÍTULO 2. Aplicación de Usuario 19 2.4. Interfaz gráfica La interfaz gráfica de la aplicación ha sido implementada en SWT, desarrollado por la fundación Eclipse. Está estructurada en paneles con una barra de estado que permite pasar de uno a otro. En este apartado se da una breve explicación de SWT y el funcionamiento de cada panel de la aplicación. 2.4.1. SWT SWT es una librería para crear interficies gráficas en Java, utilizando los componentes nativos de la plataforma donde se ejecuta la aplicación. Esta es la gran diferencia con Swing [8], la librería para creación de interfaces gráficas para Java. Mientras Swing copia los componentes nativos del sistema, SWT los utiliza. Esto quiere decir que un mismo código, se visualiza en cada sistema operativo como si hubiera sido creado para ese SO específicamente. 2.4.2. Sala de inicio Este es el panel principal de la aplicación que un usuario ve cuando la inicia. En él se encuentra un menú con las opciones de conectarse al servidor, jugar en local, opciones de ayuda e información. 2.4.2.1. Conexión al servidor En este submenú están los datos de conexión al servidor: el nombre de usuario y su contraseña, identificador del usuario en el servidor y el que verán los demás usuarios; puerto de escucha de la aplicación, por donde recibirá los mensajes del servidor y otros usuarios; y por último, la dirección IP y puerto del servidor central. La figura 2.4 muestra este submenú. Fig. 2.4 Conexión al servidor 20 2.4.2.2. Implementación de un juego de mus en red sobre SIP Jugar en local Submenú que permite jugar contra tres motores de inteligencia artificial. Se puede elegir las opciones de la partida. No hace falta conectarse a ningún servidor. La figura 2.5 muestra este submenú. Fig. 2.5 Juego con IA 2.4.3. Sala de espera Una vez el cliente se conecta al servidor se habilita este panel. El panel está dividido en tres partes. Permite gestionar la lista de amigos, crear y unirse a partidas del servidor y enviar mensajes mediante el chat. La figura 2.6 muestra una captura de pantalla de este panel. Fig. 2.6 Sala de Espera CAPÍTULO 2. Aplicación de Usuario 2.4.3.1. 21 Lista de usuarios En la parte izquierda se encuentra el panel de usuarios con dos pestañas, en la primera están los usuarios conectados en ese momento y en la segunda se muestra la lista de amigos, divididos entre conectados y no conectados. En la figura 2.7 se muestra una lista de amigos. Fig. 2.7 Lista de amigos El panel de usuarios permite, con el botón derecho, abrir un menú para agregar/eliminar a un usuario de la lista de amigos o invitar a un usuario a una partida creada. En la figura 2.8 se muestra una captura de este menú. Debajo de la lista, hay un botón para agregar un nuevo amigo de forma manual, conociendo su nombre. Fig. 2.8 Menú del ratón 22 2.4.3.2. Implementación de un juego de mus en red sobre SIP Zona de partidas Este panel esta situado en la parte central de la sala de espera. En la zona superior se muestra las partidas creadas, tanto si están en juego como en espera de otros jugadores. En la parte inferior se ubica el menú para crear partidas, con todos los valores para crearla. Fig. 2.9 Zona de partidas de la sala de espera En la derecha del panel está el chat global de la aplicación. Sirve para que los usuarios conectados puedan comunicarse. Los mensajes que escriben los usuarios en este chat se envían al servidor, el cual los replica al resto. Además, el servidor utiliza el chat para notificar al usuario las acciones que realiza, como crear partidas, empezarlas o crear/eliminar inteligencia artificial. 2.4.4. Sala de juego El panel de la Sala de juego es donde se juega la partida. En este panel hay dos zonas diferenciadas: 2.4.4.1. Tapete El tapete donde se disputa la partida. Se muestran las cartas, los botones de acción y las acciones de los otros jugadores. Cuando se pueda tomar una CAPÍTULO 2. Aplicación de Usuario 23 decisión en el juego se habilitarán los botones correspondientes, resaltando en amarillo la selección. Fig. 2.10 Tapete de juego 2.4.4.2. Cuentas En la parte derecha está la información de la partida, con los resultados mostrados por parejas. El usuario ve su pareja resaltada en amarillo y los envites vistos están entre paréntesis. Hay un botón de abandonar la partida, por si un jugador quiere salir de la partida. También hay un chat interno donde, además de permitir a los jugadores la comunicación entre ellos, se les informa del transcurso de la partida. El chat de la partida no pasa por el servidor central, sino que es el mismo jugador quien envía los mensajes al resto. Fig. 2.11 Información de la partida 24 2.4.4.3. Implementación de un juego de mus en red sobre SIP Ventana de resultados de la baza Cuando acaba una mano se informa a todos los jugadores del recuento de puntos mediante una ventana. Si es el final de la partida se pregunta si desean volver a jugar con los mismos compañeros, reiniciándola. La partida se reinicia sólo si todos los jugadores humanos están de acuerdo. Fig. 2.12 Ventana de resultado final de mano 2.4.2. Barra Estado La barra de estado permite cambiar de panel mediante botones, siempre que estos estén activos. Por ejemplo, si un jugador no está conectado no podrá acceder a la sala de espera, ni a la sala juego. También aporta información acerca del estado de la conexión. Si el usuario está conectado o no, su nombre y el número total de conectados. CAPÍTULO 3. Servidor Ágora 25 CAPÍTULO 3. Servidor Ágora 3.1. Introducción En este capítulo explicaremos cómo funciona el servidor central que controla los usuarios conectados, las listas de amigos de cada uno y gestiona las partidas. La información se almacena de forma permanente en una base de datos. Nuestro servidor central llamado Ágora, en honor al punto de reunión de las ciudades (polis) griegas, tiene ese mismo objetivo de reunir a los usuarios permitiéndoles comunicarse a través de él. En cambio, una vez se inicia la partida de mus, la comunicación pasa a ser totalmente independiente del servidor central. El servidor crea diálogos SIP con los usuarios. Todos los mensajes intercambiados entre el servidor y los usuarios se envían mediante el diálogo que mantiene el servidor con cada uno. El servidor Ágora controla a todos los usuarios conectados, sus listas de amigos, las partidas creadas y el chat principal de la aplicación. Este chat, además de permitir la comunicación entre todos los usuarios conectados, también sirve para mostrar mensajes del servidor. El servidor se ha implementado siguiendo el RFC 4579 [2], donde se dan las recomendaciones para crear eventos y que los usuarios se suscriban a ellos mediante el mensaje SUBSCRIBE. Una vez hecha la suscripción, los usuarios recibirán la información del estado del evento con el mensaje NOTIFY. La información que define el estado actual del evento esta en formato JSON, y contiene los jugadores conectados, las partidas creadas y sus jugadores. Este mensaje se enviará siempre que haya algún cambio en el evento: cuando entre o salga un jugador, se cree una partida o un jugador entre en una partida. En Ágora sólo hay creado un evento, mus, y todos los clientes se suscriben a él al conectarse. 3.2. Conexión al Ágora Para conectarse al servidor, el usuario envía un mensaje INVITE. Este mensaje contiene el nombre de usuario y su contraseña. El servidor comprueba en la base de datos que el nombre sea correcto y corresponda con la contraseña. Después de hacer estas comprobaciones se responde con un mensaje ACK positivo o negativo. Si es positivo, el cliente confirma el proceso enviando otro ACK. Estos tres mensajes forman el 3 way handshake, necesario para crear el diálogo SIP entre el servidor y el cliente. 26 Implementación de un juego de mus en red sobre SIP A continuación, el servidor envía al cliente la información del evento mus: los usuarios conectados y partidas creadas. Si es un usuario ya registrado se le envía la lista de amigos en el caso de que tenga. En este momento, el cliente aún no está suscrito al evento mus. El servidor envía al cliente información sobre el evento mus sin que esté suscrito a él para seguir el esquema del RFC 4579 [2]. En él se detalla que antes de suscribirse a cualquier evento, el servidor debe enviar la información de los eventos disponibles. Así un cliente puede elegir a cual suscribirse. En nuestro caso, sólo hay un evento y por eso sólo se envía la información de éste. Después de recibir los datos, el cliente envía al servidor el mensaje SUBSCRIBE para suscribirse al evento mus. Cuando lo recibe el servidor, almacena en una tabla de hash 2el nombre del usuario con la información de su diálogo correspondiente, y la mantiene mientras esté conectado. Cuando un nuevo usuario se conecta la información del evento mus se modifica. El servidor envía un mensaje NOTIFY a todos los usuarios suscritos al evento para actualizar la información. Al recibir este mensaje todos los usuarios reemplazan la información antigua por la nueva. Así, todos los usuarios suscritos mantienen la misma información actualizada con el servidor y la muestran por pantalla. Después de todo este proceso el usuario esta conectado y suscrito correctamente al Ágora: está listo para jugar. La figura 3.1 resume todo el intercambio de mensajes, incluyendo la creación del diálogo y la suscripción al evento mus. Fig. 3.1 Intercambio inicial de mensajes 2 Tabla de Hash: estructura de datos que asocia claves con valores. Permite recuperar los datos a partir de la clave. CAPÍTULO 3. Servidor Ágora 27 3.3. Desconexión del Ágora Cuando un jugador se quiere desconectar del servidor, envía un mensaje SIP del tipo BYE. A diferencia de los demás mensajes SIP, el BYE no necesita respuesta, así que no tendrá que esperar que el servidor conteste. Al recibir un BYE, Ágora tiene que eliminar el usuario de la lista de conectados. Primeramente, para evitar enviar mensajes NOTIFY a clientes que no están conectados, elimina el diálogo y el usuario de la lista de conectados. Antes de notificar la salida a los demás usuarios, comprueba el estado que se encontraba el usuario saliente. • Si estaba jugando una partida y él era el creador, la partida se acaba. Se notifica a los restantes jugadores de la partida que el creador se ha desconectado y vuelven a la sala de espera. • Si se encontraba jugando una partida pero no era el creador, será reemplazado por un motor de inteligencia artificial que jugará por él, hasta que finalice la partida o vuelva a conectarse. • Si estaba en una partida de la sala de espera de la que él era creador, la partida es eliminada si no más jugadores. En caso que haya un jugador, éste pasará a ser el creador de la partida. Una vez verificado el estado en que se encontraba, el servidor actualiza la clase datos donde guarda el estado del evento y lo envía a todos los usuarios conectados en ese momento. Ágora se encarga de comunicar a los jugadores de una partida que ésta finaliza. El motor de juego se limita únicamente a controlar el flujo de la partida. El servidor central es el responsable de controlar la presencia de los jugadores, y detectar si éstos se desconectan o caen de la red. 3.4. Presencia en el servidor El servidor central Ágora se encarga de mantener informados a sus clientes de los usuarios que están conectados en cada momento. Cuando un jugador se desconecta, como hemos explicado en el apartado anterior, el servidor recibe el mensaje BYE y puede notificar a los demás la salida. Si un jugador se desconecta sin enviar ningún tipo de mensaje al servidor, éste no se da cuenta de la caída y por consiguiente tampoco puede avisar a los usuarios. Para evitar este problema, hemos aprovechado el método de la pila SIP encargado de controlar el tiempo de recepción de una respuesta en un diálogo. Si no se recibe la respuesta en el tiempo establecido, la pila SIP crea un temporizador que permite actuar. Este tiempo tiene un valor de 64*T1 donde T1 28 Implementación de un juego de mus en red sobre SIP tiene un valor inicial de 500ms. El valor es configurable, pero el definido por defecto es más que suficiente, ya que da un margen de 32 segundos. Para utilizar este tiempo de respuesta, hemos creado un mensaje específico que servirá para comprobar si los usuarios están conectados. Este mensaje es del tipo KEEP_ALIVE y el servidor lo envía a todos los diálogos que tiene en ese momento. Si la respuesta no llega en el periodo establecido, por defecto 32 segundos, el servidor considera que el cliente que no ha respondido está desconectado y lo elimina siguiendo el mismo proceso que cuando recibe un BYE. Los mensajes KEEP_ALIVE se envían con un periodo variable de entre 36 y 42 segundos, un tiempo mayor que los 32 segundos establecidos del timeoutEvent. Si este periodo fuera menor, además de enviar más mensajes de los necesarios, el servidor detectaría por cada mensaje enviado más de un timeoutEvent, y sólo uno es útil para eliminar al usuario. La figura 3.2 es un ejemplo del intercambio de mensajes usado en el control de presencia de un usuario. Fig. 3.2 Protocolo de mensajes para el control de presencia CAPÍTULO 3. Servidor Ágora 29 3.5. Información persistente 3.5.1. Base de datos Para guardar los datos persistentes tales como el nombre de usuario, la contraseña y la lista de amigos, Ágora dispone de una base de datos simple donde guardar toda esta información. La base de datos se compone de tres tablas: la de jugadores, la de amigos y la de peticiones de amigo. Las dos primeras están relacionadas mediante un identificador y la última almacena las peticiones de amigo cuando no está conectado el usuario receptor. 3.5.1.1. Modelo Entidad-Relación de jugadores y amigos Fig. 3.3 Modelo E-R de la tabla jugador y la de amigo En la figura 3.3 se muestra la relación entre la tabla de jugadores y la tabla de amigos. Según esta relación, un jugador puede tener N amigos. En la primera tabla se guardan todos los nombres de los jugadores que se han conectado al servidor con su contraseña. Además, cada jugador tiene asignado un identificador que se utiliza para encontrar sus amigos. La segunda tabla almacena todos los amigos de los jugadores. Cada entrada de la tabla tiene el identificador del jugador y su amigo. Para encontrar a todos los amigos de un jugador con un determinado identificador, basta con hacer una consulta a la tabla amigos buscando por el identificador. 30 Implementación de un juego de mus en red sobre SIP 3.5.1.2. Tabla de peticiones de amigo Esta tabla almacena las peticiones que hace un usuario a otro usuario que no este conectado en ese momento. Es una tabla simple con dos columnas, la primera guarda el nombre del que hace la petición y la segunda el que la recibe. Cuando se realice la petición al “futuro amigo”, ésta se borrará de la tabla. 3.5.1.3. SQLite Para crear la base de datos y gestionarla se ha utilizado la librería Java SQLite JDBC [12] que permite utilizar SQLite en cualquier sistema operativo. SQLite es un sistema de gestión de bases de datos, que utiliza el lenguaje SQL [5]. A diferencia de los sistemas de gestión de bases de datos cliente-servidor, SQLite no es un proceso independiente con el que el programa principal se comunica. En lugar de esto, SQLite pasa a ser una parte del programa, esto mejora la eficiencia, ya que las llamadas a funciones son más eficientes que la comunicación entre procesos. Entre sus características más importantes destacamos: • No necesita instalación. • No hay un proceso servidor que necesite iniciarse o pararse. • No necesita archivos de configuración. • No necesita administrador para gestionar la base de datos. 3.5.2. Registro en Ágora El registro en el servidor central se realiza la primera vez que un usuario utiliza la aplicación. Los datos de conexión, nombre de usuario y contraseña, se guardan en la base de datos. Las próximas veces que el usuario se conecte al servidor, éste comprobará que la contraseña coincida con la almacenada en la base de datos, en caso negativo no podrá conectarse. Para no guardar la contraseña en claro dentro de la base de datos se le aplica una función resumen SHA-1.3 3 SHA-1 (Secure Hash Algorithm): función de Hash que genera un resumen de 20Bytes, este resumen no es reversible. CAPÍTULO 3. Servidor Ágora 31 3.5.3. Lista de amigos Los usuarios de la aplicación disponen de una lista privada de contactos, llamada lista de amigos. Gracias a esta lista el usuario puede encontrar a sus amigos de manera sencilla y ver su estado de conexión. Se puede modificar añadiendo o eliminando usuarios, así como invitar a un amigo a una partida creada. Ser amigo de un usuario implica reciprocidad, es decir, si A es amigo de B, B también lo será de A. Fig. 3.4 Ejemplo de lista de amigos El servidor Ágora, como ya se ha explicado, guarda la lista de amigos de cada usuario. Esta lista se envía al usuario cada vez que se conecta al servidor y cada vez que se modifica. El mensaje utilizado es LISTA_AMIGOS, que forma parte de la mensajería propia transportada mediante mensajes SIP, explicada en la sección 3.7. Para crear la lista, el servidor realiza una consulta a la tabla amigos de la base de datos mediante el identificador de usuario, almacena el resultado y lo envía. La lista recibida sólo contiene los nombres de los usuario, estén conectados o no. Para saber el estado de conexión de cada amigo, el cliente compara los nombres de los amigos con los usuarios conectados. La figura 3.4 es una captura de la aplicación de cliente mostrando la lista de amigos. 3.5.3.1. Agregar un amigo a la lista Un usuario conectado al servidor tiene dos formas de agregar nuevos amigos a su lista: mediante el botón derecho del ratón o introduciendo el nombre del amigo manualmente. Esto permite añadir a alguien sin la necesidad de que esté conectado, sólo sabiendo su nombre de usuario. Para el servidor los pasos a seguir serán los mismos, en ambos casos se envía un mensaje INVITAR_AMIGO. A continuación se explica el proceso que sigue el servidor para agregar un nuevo amigo de un usuario. Pueden surgir dos problemas: que el usuario no esté conectado o que el nombre introducido no exista. El proceso de agregar un amigo controla estos problemas. 32 Implementación de un juego de mus en red sobre SIP Al recibir el mensaje INVITAR_AMIGO el servidor comprueba, en la tabla de jugadores de la base de datos, que el nombre de usuario exista y si no existe contesta con una respuesta negativa, dando por terminado todo el proceso. Una vez comprobada la existencia del usuario, se verifica que no sean ya amigos. Si esto es correcto, se verifica que el usuario al que se realiza la petición esté conectado. Si lo está recibirá una petición QUIERES_SER_AMIGO. Si no está conectado, se guarda la petición en la tabla de peticiones de amigo. Cuando el usuario se vuelva a conectar, el servidor mirará en la tabla las peticiones pendientes, y si hay alguna la envía en ese momento y la borra de la tabla. Al recibir la petición QUIERES_SER_AMIGO, al usuario se le abrirá una ventana preguntando si lo acepta como amigo. En caso de que acepte, el servidor notifica a los dos usuarios la nueva amistad y les envía su lista de amigos actualizada. Si el jugador que recibe la petición no acepta, el servidor notificará al usuario que realizó la petición la respuesta negativa. La figura 3.5 muestra un diagrama de flujo del comportamiento del servidor cuando le llega el mensaje INVITAR_AMIGO, en él se ven todas las posibles combinaciones. En la figura 3.6 se ve el intercambio de mensajes realizado en este proceso. Fig. 3.5 Diagrama de flujo para añadir un nuevo amigo CAPÍTULO 3. Servidor Ágora 33 Fig. 3.6 Protocolo de mensajes para añadir nuevo amigo 3.5.3.2. Eliminar amigos Como ya se ha dicho, un usuario puede modificar su lista de amigos, esto incluye eliminar un amigo de ella. Cuando se elimina a un amigo de la lista, también se borra de la lista del usuario eliminado. Para eliminar a un amigo el usuario ha de seleccionarlo con el botón derecho, aparece un menú desplegable con la opción de borrarlo. Se envía al servidor un mensaje ELIMINAR_AMIGO, especificando en el campo de datos el nombre del amigo. El servidor al recibir el mensaje comprueba que el jugador exista y que sean amigos. Si es correcto elimina al amigo de la tabla de amigos, esté o no conectado. Si el usuario eliminado está conectado, recibirá un aviso de que han dejado de ser amigos. Finalmente el servidor envía a los dos usuarios sus listas de amigos actualizadas. En la figura 3.7 se encuentra el diagrama de flujo de este proceso, donde Alicia quiere eliminar a Blas de su lista de amigos. 34 Implementación de un juego de mus en red sobre SIP Fig. 3.7 Diagrama de flujo para eliminar un amigo 3.6. Control de partidas Como se ha explicado hasta ahora, el servidor Ágora controla el estado de los usuarios mientras están conectados y es el encargado de distribuir la información del evento mus, cuando hay un cambio en él. Un usuario puede crear o unirse a una partida que se encuentra a la espera de jugadores. El servidor es el encargado de detectar cuando ésta puede empezar, es decir, cuando hay cuatro jugadores en ella. Entonces, envía al creador de la partida toda la información necesaria para que éste cree el motor de juego (direcciones IP y nombres de los jugadores, parámetros iniciales de la partida). En el siguiente apartado se explica la clase datos, donde se guarda toda la información del evento mus, y cómo el servidor controla el estado de los jugadores en una partida. CAPÍTULO 3. Servidor Ágora 35 3.6.1. Clase datos En la clase datos se guarda la información actualizada del evento mus. Contiene los usuarios conectados y las partidas creadas, con los jugadores que hay en ellas y sus parámetros iniciales. Cuando un usuario crea, se une o elimina una partida lo comunica al servidor central. Éste se encarga de modificar los datos del evento y distribuirlos a todos los usuarios con un mensaje NOTIFY. Queda claro que sólo el servidor modifica los datos, de acuerdo con las peticiones de los clientes, y éstos muestran en su interfaz gráfica los datos que envía el servidor. Fig. 3.8 Esquema de la clase datos La clase datos es serializada mediante JSON, para enviarla a los usuarios. Cada usuario la deserializa para leer los datos y actualizar su interfaz gráfica. Estos datos, como se ve en la figura 3.8 contienen una lista de los usuarios conectados y otra lista con las partidas creadas. Cada partida tiene unas propiedades: 1. Nombre de la partida: nombre que identifica la partida, lo elige el creador de la partida y no se puede repetir, ni modificar. 2. Estado: es el estado en que se encuentra la partida. Hay dos estados: esperando, cuando en la partida hay menos de cuatro jugadores, sean motores de inteligencia artificial o jugadores humanos; y jugando, cuando hay cuatro jugadores dentro de ella. Si la partida finaliza, simplemente se borra. 36 Implementación de un juego de mus en red sobre SIP 3. Creador: es el jugador que ha creado la partida. Es el único que puede invitar a otros jugadores a su partida o añadir inteligencia artificial en cualquier posición de la mesa. Si el creador se desconecta y hay más jugadores, el creador pasa a ser el siguiente jugador en unirse a la partida. 4. Jugadores: es la lista de los cuatro jugadores de la partida. En un principio sólo está el creador, y se va llenando a medida que se unen otros jugadores, humanos o no. 5. Banquillo: lista donde se guardan los jugadores de una partida que se desconectan de ésta. Si un jugador desconectado vuelve a conectarse al servidor, y la partida aún existe, se le dará la opción de seguir jugando en la misma partida. Si contesta negativamente, el servidor lo elimina del banquillo. 6. Valores iniciales: aquí se recogen los valores de puntos, juegos y vacas a los que se juega en la partida. 3.6.2. Creación de la partida Para crear una partida, un usuario conectado dispone del panel correspondiente en la sala de espera, como se muestra en la figura 2.6. Tiene que especificar un nombre y los valores iniciales de la partida. El nombre es un campo obligatorio, si el usuario no lo escribe, se creará uno aleatorio. Una vez introducidos los datos de la partida a crear, se envía un mensaje CREAR_PARTIDA al servidor. Éste verifica que el nombre de la partida no esté repetido y que el jugador que la crea no esté en otra partida. Si todo se cumple, crea la nueva partida y actualiza la clase datos. En caso de que no se cumpla, el servidor envía un mensaje denegando la partida al usuario. Siempre que hay un cambio en la clase datos se envía a todos los usuarios con el mensaje NOTIFY. Este usuario pasa a ser el creador de la partida y el único que puede introducir motores de inteligencia artificial en ella, a no ser que el servidor introduzca alguno como substituto de un jugador caído en mitad de la partida. Finalizado correctamente el proceso, la partida creada está en disposición de aceptar jugadores. Éstos se situarán en las cuatro posiciones de la partida agrupadas por parejas. 3.6.3. Estado esperando Cuando el servidor acepta la partida, y los usuarios reciben los datos actualizados, la nueva partida aparece en el panel de partidas de la interfaz gráfica, con el estado esperando. Los usuarios podrán unirse en las posiciones libres de la partida. CAPÍTULO 3. Servidor Ágora 37 El creador de la partida es el único que puede añadir un motor de inteligencia artificial en una posición libre. Para añadir uno, envía un mensaje QUIERO_IA al servidor. Éste elije un nombre aleatorio de una lista para la inteligencia artificial, y lo añade en la partida. Actualiza la clase datos y la envía a todos los usuarios. Si el creador abandona mientras la partida está en estado esperando y hay otro jugador en la partida, el servidor lo nombrará creador de la partida, teniendo las mismas opciones que el anterior creador. En el caso de que se marche el creador y no hubiera otro jugador humano esperando, el servidor borrará la partida. 3.6.3.1. Invitar a un jugador a la partida El creador tiene la opción de invitar a su partida a otros usuarios conectados. En la lista de usuarios aparece, apretando el botón derecho del ratón, un menú desplegable con las posiciones libres de la partida. Seleccionando la posición, el creador invita al usuario a jugar en ella. Sólo se podrá invitar a una partida a usuarios que no estén en ninguna. La invitación se envía al servidor central mediante un mensaje INVITAR_PARTIDA. Éste comprueba si el usuario está conectado, si lo está se le envía un mensaje de invitación a la partida, especificando la posición de la mesa en la que ha sido invitado. Al recibir el mensaje INVITACIÓN_PARTIDA, el receptor ve un dialogo donde elegir si aceptar la invitación o rechazarla. Si la acepta, el servidor comprueba que la posición sigue vacía y añade el jugador a la partida, se hace esta comprobación porque en el proceso un tercer usuario se ha podido unir a la partida ocupando la posición libre. Si por el contrario rechaza la invitación, el servidor avisa al creador que el usuario la ha declinado. La figura 3.9 muestra el intercambio de mensajes del creador invitando a la partida a un usuario, y éste acepta la invitación. Fig. 3.9 Protocolo de mensajes de invitar a la partida 38 Implementación de un juego de mus en red sobre SIP Como resumen del proceso de creación de una partida y la espera de jugadores se incluye la figura 3.10. Es un diagrama que muestra las posibles situaciones. El siguiente apartado 3.6.4, detalla el inicio de la partida y cómo lo detecta el servidor central. Fig. 3.10 Diagrama del estado de espera de la partida 3.6.4. Empezar la partida Como ya se ha comentado, el servidor no crea el motor de juego, únicamente se limita a controlar el estado de las partidas. El servidor detecta cuando las partidas están listas para empezar, es decir, cuando una partida tiene cuatro jugadores, sean humanos o no. Si está lista, el servidor se comunica con el creador de la partida. Éste es el encargado de crear el motor de juego y los motores de inteligencia artificiales necesarios. El servidor envía un mensaje EMPEZAR_PARTIDA al creador, en él se incluye toda la información necesaria para crear el motor de juego y empezar a jugar: CAPÍTULO 3. Servidor Ágora 39 • El número de motores de inteligencia artificial. • El nombre, la dirección IP y el puerto de cada jugador de la partida, incluyendo también al creador. • El nombre de la partida y los valores iniciales. Cuando el creador recibe estos datos ya está listo para inicializar el motor de juego, y crear el motor de inteligencia, si es necesario. Para el desarrollo de la partida no se necesita comunicación con el servidor central. Sin embargo al estar suscritos al evento mus, los jugadores siguen recibiendo los mensajes NOTIFY y pueden seguir utilizando la sala de espera, la lista de amigos y todas las opciones que ofrece el servidor central. 3.7. Mensajería Para el envío de información entre los usuarios y el servidor central, una vez establecida la conexión, se han creado mensajes propios enviados sobre el mensaje SIP MESSAGE. La figura 3.11 muestra la estructura general de estos mensajes. Fig. 3.11 Estructura general del mensaje 3.7.1. Funcionalidades del servidor INFO • • • • Origen: servidor central Destino: usuario Contenido: datos del evento mus Función: informar de los eventos del servidor en el inicio de la conexión KEEP_ALIVE • Origen: servidor central • Destino: todos los usuario • Contenido: ninguno • Función: comprobar la presencia de los usuarios mediante el control de la respuesta al mensaje 40 Implementación de un juego de mus en red sobre SIP CHAT_GLOBAL • Origen: usuario • Destino: servidor central • Contenido: mensaje del usuario • Función: ser reenviado a todos los usuarios conectados CHAT_GLOBAL_BROADCAST • Origen: servidor central • Destino: todos los usuario • Contenido: mensaje y nombre del usuario que lo escribió • Función: mensaje a escribir en el chat 3.7.2. Crear, unirse y salir de una partida CREAR_PARTIDA • Origen: usuario • Destino: servidor central • Contenido: nombre, puntos, juegos y vacas de la partida • Función: crear una nueva partida en el servidor, la respuesta informa si ha sido aceptada por el servidor QUIERO_JUGAR • Origen: usuario • Destino: servidor central • Contenido: nombre de la partida y posición • Función: indica que un usuario quiere unirse a una partida creada QUIERO_IA • Origen: creador partida • Destino: servidor central • Contenido: nombre de la partida y posición • Función: indica que el creador quiere añadir una IA a la partida ELIMINAR_IA • Origen: creador partida • Destino: servidor central • Contenido: nombre de la IA y de la partida • Función: indica que el creador quiere eliminar una IA . ABANDONAR_PARTIDA • Origen: jugador de una partida • Destino: servidor central • Contenido: nombre de la partida • Función: el jugador abandona una partida a la que está unido CAPÍTULO 3. Servidor Ágora 41 EMPEZAR_PARTIDA • Origen: servidor central • Destino: creador partida • Contenido: información necesaria para crear el motor de juego • Función: mensaje enviado cuando se detecta que una partida hay cuatro jugadores y puede empezar ELIMINAR_PARTIDA • Origen: creador partida • Destino: servidor central • Contenido: nombre de la partida • Función: borrar una partida finalizada del servidor central, la respuesta confirma la eliminación ENVIAR_IPS • Origen: motor de juego • Destino: cuatro jugadores de la partida • Contenido: direcciones IP • Función: inicializar los datos de los jugadores para jugar la partida DECIR_NOMBRES • Origen: motor de juego • Destino: cuatro jugadores de la partida • Contenido: nombres de los cuatro jugadores y el de la partida • Función: inicializar los datos de los jugadores para jugar la partida ESTADO_PARTIDA_LATA • Origen: motor de juego • Destino: jugador introducido en la partida iniciada • Contenido: información actualizada del estado de la partida • Función: actualizar los valores necesarios para que un jugador se una a la partida iniciada 3.7.3. Introducir jugador en una partida iniciada METER_LATA • Origen: servidor central • Destino: creador de la partida • Contenido: posición dentro de la partida y nombre de la IA • Función: indicar que ha de crear una IA en una partida iniciada 42 Implementación de un juego de mus en red sobre SIP METER_RETORNADO • Origen: servidor central • Destino: creador de la partida • Contenido: posición dentro de la partida, nombre y dirección IP del jugador caído • Función: reintroducir un jugador caído en una partida iniciada RETORNO_JUGADOR • Origen: servidor central • Destino: jugador • Contenido: nombre de la partida ya iniciada • Función: preguntar al jugador si quiere volver a entrar en la partida que estaba jugando 3.7.4. Gestión de la lista de amigos INVITAR_AMIGO • Origen: usuario • Destino: servidor central • Contenido: nombre usuario a quien va dirigida la petición • Función: añadir un usuario a la lista de amigos, si todo es correcto el servidor envía un QUIERES_SER_SU_AMIGO al usuario del contenido QUIERES_SER_SU_AMIGO • Origen: servidor central • Destino: usuario • Contenido: nombre usuario que creó la petición • Función: preguntar a un usuario si quiere ser amigo de otro NUEVO_AMIGO • Origen: servidor central • Destino: usuario • Contenido: resultado de la petición de hacer nuevo amigo • Función: mensaje final del proceso de añadir un amigo a la lista LISTA_AMIGOS • Origen: servidor central • Destino: usuario • Contenido: nombres de los amigos • Función: actualizar la lista de amigos de un usuario ELIMINAR_AMIGO • Origen: usuario • Destino: servidor central • Contenido: nombre del amigo • Función: eliminar a un amigo de la lista de amigos CAPÍTULO 3. Servidor Ágora INVITAR_PARTIDA • Origen: creador partida • Destino: servidor central • Contenido: nombre invitado, nombre partida y la posición • Función: el creador de una partida invita a un usuario a jugar en ella, la respuesta confirma la petición 43 CAPÍTULO 4. Motor de juego 45 CAPÍTULO 4. Motor de juego 4.1. Introducción En este capítulo se explica la estructura del motor de juego y los objetos que lo forman. En la sección 4.3 hay una breve explicación de cómo jugar al mus. El motor de juego hace la función de servidor dentro de una partida, es el encargado de gestionar el flujo de la partida. Se crea un motor por cada partida en juego, en el usuario con rol de creador. Se implementa esta estructura para liberar al Ágora del intercambio de mensajes propio de cada partida, ya que éste no es su cometido tal y como se ha visto en el capítulo 3. Esta estructura también permite jugar una partida en local, ya que no hay necesidad de comunicarse con el servidor central. El motor de juego está formado por una parte de red, encargada de crear, enviar y recibir los mensajes a través de SIP, y un motor que es el componente que controla el flujo del juego y el que marca el orden de las peticiones. En la figura 4.1 se muestra la arquitectura de la partida. Fig. 4.1 Arquitectura de la partida 4.2. Esquema del motor de juego El motor de juego es un objeto de la clase MusServer, este objeto es el servidor de una partida, por lo tanto, ha de disponer de una pila SIP para el envío/recepción de los mensajes de jugadores y conocer el flujo de una partida de mus. Los siguientes objetos proporcionan estas funcionalidades: 46 Implementación de un juego de mus en red sobre SIP • Engine: objeto que sabe cómo jugar al mus, es el encargado de repartir las cartas, decir las fases del juego, hacer las peticiones a los jugadores, llevar el control de las puntuaciones, etc. Se comunica llamando a métodos del MusNetController. • NetController: interfaz donde se definen los métodos necesarios para jugar una partida de mus en red. • MusNetController: objeto que implementa la interfaz NetController, es el punto intermedio entre el Engine y la pila SIP. Es el encargado de construir y enviar los mensajes según le marque el Engine, también ha de interpretar las respuestas de los jugadores para devolverle la información. • MusSipServer: la pila SIP del motor de juego, con los métodos propios para el envío y recepción de mensajes SIP. La figura 4.2 presenta el diagrama de clases del motor de juego. Fig. 4.2 Diagrama de clases del motor de juego 4.2.1. Inicio de la partida Una vez creado el motor de juego, con todos sus objetos, la partida puede dar comienzo. Primero de todo, el motor de juego envía a los jugadores la información de la partida: direcciones IP y nombres de todos los jugadores, nombre de la partida, y por último, los valores iniciales de puntos, juegos y vacas. CAPÍTULO 4. Motor de juego 47 Cuando el jugador recibe toda la información relacionada con la partida, puede crear la sala de juego de la interfaz gráfica, con los valores adecuados. La partida está lista para jugarse. Durante el transcurso de la partida los jugadores responden a las peticiones del motor de juego directamente y además, cuando sea necesario, envían mensajes a los otros jugadores informando de sus acciones. De esta forma la interfaz gráfica se actualiza cada vez que un jugador realiza una acción. 4.2.2. Fin de la partida Cómo se ha explicado en la sección 2.4.4, correspondiente a la interfaz gráfica, al finalizar una partida aparece una ventana para que el jugador decida si quiere jugar otra partida con los mismos compañeros. El motor de juego controla las respuestas de los jugadores. Si todos están de acuerdo, se reinician las cuentas y empieza una nueva partida. Si no avisará al servidor central de que la partida ha finalizado. Este borrará la partida y avisa a los jugadores. 4.3. El juego del mus En este apartado se hace una pequeña explicación de cómo se juega al mus, sus características y los lances que se juegan. El objeto Engine implementa el funcionamiento del juego. El mus es un juego de cartas de baraja española de origen vasco. Los participantes en el juego son cuatro jugadores agrupados por parejas, situados en la mesa enfrente de su compañero. La baraja utilizada es una baraja española de 40 cartas (sin ochos ni nueves) y a cada jugador se le reparten cuatro cartas. Cada vez que un jugador reparte las cartas, el jugador que está a su derecha es mano, el segundo es el que esta a la derecha del mano y así hasta llegar al que reparte, que es el último y se denomina postre. El mazo se sitúa en la mesa entre el último jugador y el mano. El palo de la carta es indiferente, sólo importa su valor simbólico. Se juega con ocho reyes y ocho ases, de manera que los treses equivalen a reyes y los doses equivalen a ases. El valor de las cartas es el siguiente: rey, caballo, sota valen 10, ases y doses valen 1 y las demás cartas tienen su valor numérico. El objetivo del juego es ganar más vacas que el contrario. Para ganar una vaca hay que hacer más juegos que la otra pareja y para ganar un juego hay que sacarse antes que sus oponentes las piedras o puntos definidas en la partida. Todos estos valores los define el creador en el momento de crear la partida. Se puede elegir entre 30 o 40 piedras y 1, 3 o 5 juegos y los mismos valores para las vacas de la partida. 48 Implementación de un juego de mus en red sobre SIP En el juego podemos diferenciar tres partes: la fase mus, las apuestas de cada lance y el recuento de puntos. 4.3.1. Lances del juego El mus tiene cuatro lances y se apuestan en orden de: grande, chica, pares y juego. Cada lance es independiente uno a otro y hay una apuesta para cada uno. Los lances de pares y juego, tienen piedras extra por ganar. 4.3.1.1. Grande Es el primero de los cuatro lances. Un jugador tendrá mejor jugada a grande cuantos más reyes tenga, a igualdad de número de reyes, el que tenga mayor número de caballos y así sucesivamente. Si no hay reyes, la carta mayor será el caballo, si tampoco hay caballo, la sota, y así hasta el as. A igualdad de cartas ganará el jugador que sea mano respecto a otro. 4.3.1.2. Chica La chica es como la grande pero con ases. Ganará el jugador que tenga más ases, después cuatros, cincos, etc., hasta el rey, que es la peor carta en este lance. 4.3.1.3. Pares Un jugador tiene pares cuando tiene dos o más cartas iguales. Hay tres tipos de pares: el de más valor es el duples, formado por todas las cartas iguales o dos parejas; después está medias, cuando se tienen tres cartas iguales; y el par de menos valor es una pareja de dos cartas iguales. Si se empata porque dos jugadores tienen duples, medias o pareja, se tiene en cuenta el valor de la pareja formada por cartas con mayor valor a grande. En caso de que dos jugadores tengan duples, y empaten en la pareja mayor se comparará la otra pareja. Las cartas que no formen pareja no tienen ningún valor para desempatar. Si dos jugadores tienen exactamente la misma jugada, ganará el más cercano al jugador que es mano. Antes de empezar la apuesta, los cuatro jugadores dicen si tienen pares o no, empezando por el jugador mano. Sólo podrán apostar a pares aquellos jugadores que los lleven. Si nadie tiene pares no hay envite y se pasa directamente al siguiente lance. Igual ocurre si sólo una pareja tiene pares y en el recuento final se llevarán las piedras correspondientes a sus pares. CAPÍTULO 4. Motor de juego 4.3.1.4. 49 Juego o punto Un jugador tiene juego, si la suma numérica de sus cartas es mayor de 30. El juego más valioso es 31, luego 32, 40, 37, 36, 35, 34 y el peor, 33. Como en pares, antes de empezar los jugadores tendrán que decir si tienen o no, y sólo puede jugar a juego el jugador que tenga. En caso que sólo una pareja lleve juego, será la ganadora y se pasará al recuento, llevándose las piedras correspondientes a su juego. En el caso de que ningún jugador tenga juego, es decir, ninguno de ellos sume 31 o más, se jugará al punto. Ganará el jugador que tenga el valor de sus cartas más alto, siendo el más valioso aquel que sus cartas sumen 30. Todos los jugadores podrán jugar al punto, pues significa que nadie tiene juego. 4.3.2. Fase mus Una vez repartidas las cuatro cartas a cada jugador, se pregunta, empezando por el jugador mano, si se quiere dar o cortar mus. Habrá mus si los cuatro jugadores se dan mus. Si un jugador corta el mus, se empezarán los lances. Si los cuatro jugadores se han dado mus, se descartan de las cartas que deseen, y siempre tienen que descartarse de como mínimo una, empezando por el jugador mano y siguiendo el sentido antihorario. El jugador que ha repartido reparte a cada jugador un número de cartas igual a sus descartes. Cada jugador tendrá otra vez cuatro cartas y se repetirá otra vez la fase mus hasta que alguien corte el mus. Si la baraja se acaba por haber repartido todas las cartas, las cartas de los anteriores descartes se barajan y se utilizan como nueva baraja, volviéndose a repartir con ellas las veces que sea necesario. 4.3.2.1. Mus corrido En la primera fase mus del juego, se juega mus corrido. Esta regla hace que cuando un jugador da mus el mazo avanza hacia la derecha, cambiando el jugador que es mano, que será el de su derecha. El mus corrido sólo esta activo en la primera fase mus de la partida, una vez se corta ya no se utiliza. 50 4.3.2.2. Implementación de un juego de mus en red sobre SIP Diagrama de flujo de la fase mus Fig. 4.3 Diagrama de flujo de la fase mus En la figura 4.3 se muestra el desarrollo de la fase mus, desde que se barajan y se reparten las cartas, hasta que se empiezan a jugar los lances. 4.3.3. Fase de apuestas Una vez que un jugador ha cortado el mus, el jugador que es mano comenzará a jugar los diferentes lances, en el orden de grande, chica, pares y juego. En principio el jugador, puede elegir entre la opción de pasar, envidar, o echar órdago. Los jugadores hablan por su pareja, es decir que un jugador habla por él y por su pareja. El primer jugador que habla siempre es el mano o el más cercano a él hacia la derecha. Si los cuatro jugadores deciden pasar, el lance queda en paso, y en el momento de su resolución quien lo gane suma una piedra en la cuenta de su pareja. En caso del lance de punto si envida y los contrarios pasan se sumarán dos piedras. CAPÍTULO 4. Motor de juego 51 Fig. 4.4 Diagrama de flujo de las apuestas 4.3.3.1. Envite El envite es la apuesta básica del mus. No hay un número máximo de piedras envidadas, pero sí que hay un mínimo de dos piedras. Cuando una pareja envida un número de piedras, la pareja contraria puede elegir entre verlas, pasar, reenvidar o echar el órdago. Si ven las piedras, al final de los lances cuando se resuelvan, quien gane la resolución del lance que se ha visto, sumará a su pareja el número de piedras vistas. Si la pareja contraria puede elegir reenvidar, entonces pasa el turno a la pareja contraria y les toca elegir entre las mismas opciones de volver a envidar, ver órdago o pasar. Si los dos contrarios eligen pasar, la pareja que ha reenvidado sumará tantas piedras como había envidadas antes de su apuesta. La pareja contraria puede elegir echar órdago, un envite especial del mus que explicaremos en la sección 4.3.3.2. La figura 4.5 muestra el diagrama del envite. 52 Implementación de un juego de mus en red sobre SIP Fig. 4.5 Diagrama de flujo del envite 4.3.3.2. Órdago El órdago es la apuesta máxima en el mus. Cuando un jugador echa un órdago en algún lance, significa que apuesta todo un juego a ese lance. Funciona como un envite, y la pareja contraria puede elegir si ver el órdago o pasar. Si deciden verlo, se resuelve el lance de manera instantánea, se suma un juego a la pareja ganadora y se empieza otro juego. Por el contrario, si los contrarios deciden pasar al órdago, igual que el reenvite, la pareja que lo ha echado gana las piedras que había envidadas o una en caso de que no hubiera. La figura 4.6 se corresponde con el diagrama de flujo del órdago. CAPÍTULO 4. Motor de juego 53 Fig. 4.6 Diagrama de flujo del órdago 4.3.4. Fase de recuento de piedras El recuento de piedras se realiza una vez se han jugado los cuatro lances del juego. Si ha quedado algún lance en paso o un envite visto, se resuelven en el mismo orden que se han jugado y la pareja ganadora se lleva las piedras envidadas o sólo una si han pasado todos. En el caso de pares y juego, la pareja ganadora suma unas piedras extra según la jugada que tengan los jugadores de la pareja. En el caso de que se haya ganado el lance de pares, se sumarán tres piedras por duples, dos por medias y una por pareja. Si se gana juego, se sumarán tres piedras si algún jugador de la pareja ganadora tiene 31 o dos por cualquier otro juego. Cada vez que una pareja suma una piedra, se comprueba que no lleguen al número de piedras que ha definido el creador. Si llegan a ese número, han ganado el juego y se suma uno a la pareja. Una pareja puede ganar un juego sin estar en la fase de recuento, que en ese caso no se realiza. Cuando se gana un juego se comprueba también si han ganado los juegos necesarios para completar una vaca y lo mismo se hace con las vacas. Cuando una pareja gana las vacas definidas por el creador será la vencedora de la partida y ésta se acabará. Si no finaliza la partida, se vuelven a repartir otras cartas y se retorna a la fase de mus. 54 Implementación de un juego de mus en red sobre SIP Fig. 4.7 Diagrama del recuento de puntos En la figura 4.7 se explica el recuento de puntos una vez finalizados los lances de la partida. Si la partida se finaliza, el motor de juego controlará si los jugadores quieren volver a jugar como se detalla en la sección 4.2.2. Si no quieren jugar se eliminará la partida. CAPÍTULO 5. Interacción con la Inteligencia Artificial 55 CAPÍTULO 5. Interacción con la Inteligencia Artificial 5.1. Introducción A lo largo de los capítulos hemos hablado del motor de inteligencia artificial, cuando es necesario crearlo y eliminarlo, y la forma en que se comunica dentro de una partida. Hay que decir también que este motor de inteligencia artificial o IA, es desde el punto de vista de nuestro proyecto, un jugador más. No es necesario saber su funcionamiento interno para poder crearlo, ni tampoco enviarle la información con un formato diferente a la enviada para un jugador humano. La IA tiene un objeto MusJugadorIA que implementa la interfaz JugadorInterface, de esta forma utiliza los mismos métodos que un jugador humano. Lo que la IA haga con estos métodos, dentro de su código, es algo desconocido para nosotros, ya que es un proyecto aparte. Por otro lado, la IA puede crearse al inicio de una partida o en medio por ejemplo si desconecta un jugador. En el caso que una IA o un humano se introduzcan en medio de una partida deben recibir información acerca del estado actual de la partida. Por eso hay que esta información. de una, jugador toda la guardar 5.2. Estado de la partida Toda la información acerca del estado actual de la partida se almacena en un objeto de la clase EstadoPartida. En esta clase están definidos todos los atributos necesarios para que un jugador pueda engancharse a una partida y disponga de toda la información necesaria: cartas, fase que se está jugando, tanteo de la partida, saber si es su turno… Este objeto lo crea el motor de juego y lo actualiza paralelamente al desarrollo de la partida. De esta forma un jugador se puede introducir en la partida en cualquier momento y saber cómo actuar. La información referente al estado de la partida, se envía en un mensaje del tipo ESTADO_PARTIDA_LATA, explicado en la sección 3.7. El contenido de este mensaje es el objeto de la clase EstadoPartida en formato JSON. El jugador, sea IA o jugador humano, cuando recibe el mensaje inicializa su estado de partida y está en condiciones de proseguir la partida con normalidad. 56 Implementación de un juego de mus en red sobre SIP Fig. 5.1. Clase EstadoPartida 5.3. Introducir un jugador El motor de juego dispone de toda la información que necesitará un jugador para meterse en una partida iniciada, pero es el servidor central el encargado de avisarle de tal evento. Los dos casos posibles en que hay que meter jugador en una partida iniciada son, cuando un jugador humano se desconecta y se introduce una IA que lo sustituye, o cuando un jugador humano retorna a la partida y se elimina la IA que lo sustituyó. A continuación se encuentra la explicación de las acciones a realizar en cada caso. CAPÍTULO 5. Interacción con la Inteligencia Artificial 57 5.3.1. Introducir IA Cuando un usuario que está jugando una partida se desconecta del servidor central hay que introducir una IA que lo sustituya para poder proseguir con la partida. El servidor central es el encargado de notificar este cambio a los demás jugadores de la partida y de avisar al motor de juego mediante el mensaje METER_LATA para que éste cree el motor de inteligencia artificial, siguiendo el procedimiento explicado en la sección 2.2. El motor de juego enviará un mensaje ESTADO_PARTIDA_LATA con toda la información referente al estado actual de la partida a la IA y paralelamente avisará a todos los jugadores de la partida del nombre y la dirección IP del nuevo jugador. Así todos los jugadores dispondrán de la nueva información. La figura 5.2 muestra éste intercambio de mensajes. Fig. 5.2. Intercambio de mensajes para introducir una IA Durante todo este proceso la partida no se interrumpe, si le toca el turno al jugador caído habrá que esperar un pequeño intervalo hasta que el proceso de creación de la IA se complete. Cuando esté completado la IA sabrá que es su turno y proseguirá la partida. La mayor dificultad de introducir una IA en medio de una partida es actualizar correctamente el objeto estado de la partida con toda la información que necesita la IA para tomar decisiones. Si esto no es así la IA puede quedarse sin contestar y bloquear la partida. 58 Implementación de un juego de mus en red sobre SIP 5.3.2. Retorno jugador humano Cuando un usuario que estaba jugando una partida se desconecta del servidor central, se le ofrece la posibilidad de reentrar en la partida que estaba jugando. El servidor central, como ya se ha explicado, dispone de una lista de los jugadores que se han caído de una partida en juego, y han sido sustituidos por una IA. Cuando un usuario se conecta al servidor central y éste detecta que estaba en una partida que todavía esta en juego, le ofrece la posibilidad de reentrar en ella. Primero le envía al usuario un mensaje del tipo RETORNO_JUGADOR para preguntarle si desea entrar de nuevo en la partida. Si el jugador acepta volver a la partida, se inicia un proceso similar al de introducir una IA. El proceso es el siguiente: el servidor central avisa al motor de juego que un jugador vuelve a recuperar su con el mensaje METER_RETORNADO, los datos del mensaje son el nombre, dirección IP y posición dentro de la partida del jugador. Seguidamente el motor de juego envía al jugador que reentra todos los datos del estado actual de la partida. También le envía los parámetros iniciales de la partida para que se cree en la interfaz gráfica la sala de juego con las cartas, botones, etc. Si toda la comunicación ha sido correcta, se borra la IA. Para finalizar se envía a todos los jugadores de la partida el nombre y dirección IP del jugador retornado. La figura 5.3 muestra el intercambio de mensajes. Fig. 5.3. Intercambio de mensajes para meter a un jugador caído CAPÍTULO 5. Interacción con la Inteligencia Artificial 59 Al igual que en el proceso de introducir una IA, la partida sigue su curso normal, si le toca el turno al jugador que está reentrando en la partida habrá que esperar un intervalo hasta que esté preparado. El jugador verá en la interfaz gráfica toda la información con los valores actualizados de la partida, envites, puntos, juegos, vacas, etc. La mayor dificultad de todo este proceso es que el jugador cree bien la sala de juego en la interfaz gráfica, ya que dependiendo de la fase del juego en que entre debe visualizar los botones de juego adecuados para poder jugar. CAPÍTULO 6. Conclusiones 61 CAPÍTULO 6. Conclusiones Al inicio del proyecto se fijaron unos objetivos concretos de las funcionalidades que debía tener el juego de mus en red. Conseguirlas ha significado un reto, ya que ha requerido de un proceso de aprendizaje de tecnologías desconocidas para nosotros como SIP, JSON, SQLite, etc. Se ha hecho uso de implementaciones de libre distribución, y gracias a los documentos y foros de ayuda, se ha conseguido dominar su manejo. El objetivo general era conseguir un sistema de mus en red, con un sistema de presencia de los usuarios conectados a él. Para cumplir este objetivo principal se dividió en pequeños hitos más concretos y accesibles. Crear una aplicación del cliente con interfaz gráfica y, poco a poco, aumentar sus funcionalidades fue el primer hito. El aprendizaje de SWT, no exento de trabas, hizo que la interfaz gráfica creciera en prestaciones. El segundo hito consistió en crear el servidor central y conectar la aplicación de cliente a través de un diálogo SIP, en este proceso obtuvimos una idea más completa de lo que SIP nos podía ofrecer. Un tercer hito fue diseñar la aplicación para poder tratar a un jugador humano y a una inteligencia artificial sin ninguna diferencia. A partir de esta tercera meta hubo dos factores, el proyecto ya empezaba a tomar forma y teníamos un conocimiento mayor de lo que SIP ofrecía, que hicieron que pudiéramos empezar a fijar metas mayores para acercarnos al objetivo final. Estas metas fueron: implementar el control de presencia de usuarios, con sus exhaustivas pruebas; la suscripción a eventos SIP, con las diversas lecturas de RFCs; guardar la información de forma persistente en una base de datos; introducir jugadores, humanos o inteligencia artificial, en una partida ya iniciada, etc. Hay que decir que el proyecto se ha hecho entre dos personas, hecho que nos ha obligado a distribuir con antelación el trabajo y realizar una correcta planificación. Paralelamente hemos trabajado con los compañeros del proyecto del motor de inteligencia artificial, intercambiando opiniones sobre cómo tratar los puntos en que nuestros proyectos se cruzaban. En resumen, el proyecto realizado cumple los objetivos marcados. Se pueden añadir futuras mejoras cómo: - Un chat de voz, aprovechando la señalización SIP. Señas visuales en la interfaz gráfica, útiles en el mus. Nuevas funcionalidades del servidor: ránking de puntuaciones de los usuarios según partidas ganadas, partidas privadas, avatares de usuario, etc. 62 Implementación de un juego de mus en red sobre SIP 6.1 Ambientalización Este proyecto no ha presentado ningún tipo de impacto medioambiental en su realización, ni tampoco en su uso. El impacto ambiental causado durante la elaboración es el propio del uso de los ordenadores utilizados y nuestro transporte a la universidad. El proyecto permite un ahorro energético en tanto en cuanto permite a personas geográficamente distantes jugar partidas de mus sin tener que desplazarse, economizando el gasto energético. 6.2 Agradecimientos Al director de este proyecto, Sergio Machado, por su ayuda en la realización de éste y por enseñarnos a jugar al mus. A nuestros compañeros del “departamento de inteligencia artificial”, por la creación de ésta, y las prácticas de mus en el bar del campus. A todos los que participaron, profesores y alumnos, en el bloque de intensificación en sistemas telemáticos del curso 2007-1, donde se asentaron las bases de éste proyecto. A nuestras familias, por su paciencia y aguantarnos durante la confección del proyecto. A Lisa. Bibliografía 63 Bibliografía [1] “SIP: Session Initiation Protocoll”, [RFC 3261], Junio [Documentación en línea] URL: http://tools.ietf.org/html/rfc3261 2002. [2] “SIP: Call Control. Conferencing for User Agents”, [RFC 4579], Agosto 2006. [Documentación en línea] URL: http://tools.ietf.org/html/rfc4579 [3] “Internet Message Format”, [RFC 2822], Abril 2001. [Documentación en línea] URL: http://tools.ietf.org/html/rfc2822 [4] “The application/json Media Type for JavaScript Object Notation (JSON)”, [RFC 4627], Julio 2006. [Documentación en línea] URL: http://tools.ietf.org/html/rfc4627 [5] “SQL: Structured Query Language”, [ISO/IEC 9075], última revisión publicada 2006, [Documentación en línea] URL: http://www.iso.org [6] “XML (Extensible Markup Language)”. [Documentación en línea] URL: http://www.w3.org/TR/xml/ [7] “SWT (Standard Widget Tool)”. [Documentación en línea] URL: http://www.eclipse.org/swt [8] “Swing”. [Documentación en línea] URL: http://java.sun.com/docs/books/tutorial/uiswing/ [9] “JAIN-SIP”. [Documentación en línea] URL: https://jain-sip.dev.java.net/ [10] “JSON (JavaScript Object Notification”. [Documentación en línea] URL: http://www.json.org/ [11] “XSTREAM”. [Documentación en línea] URL: http://xstream.codehaus.org/ [12] “SQLite JDBC”. [Documentación en línea] URL: http://www.zentus.com/sqlitejdbc/ [13] “IETF (The Internet Engineering Task Force)”. [Documentación en línea] URL: http://www.ietf.org/ [14] “NIST (Nacional Institute of Standards and [Documentación en línea] URL: http://www.nist.gov/ [15] Sparks, R., “SIPit 20 surrey summary”, Abril 2007. [Documentación en línea] URL: http://www.ietf.org/mail-archive/web/sip/current/msg18959.html Tecnology)”. 64 Implementación de un juego de mus en red sobre SIP [16] Gil Martínez, Miguel A., “Las probabilidades en el mus. Conozca sus secretos”, Incipit editores, Madrid, Octubre 2005. [17] Johnston, Alan B., “Understanding the Session Initiation Protocol”, Artech House, Norwood (UK), 2001.