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.