API del Juego¶
Módulo con el API de websockets para la comunicación en tiempo real con los clientes, como el juego mismo o el chat de la partida.
Funcionamiento del juego¶
En esta sección se incluyen diagramas sobre la comunicación entre el cliente y el servidor de forma más visual que textualmente. Para más detalles sobre los mensajes consultar la Mensajes, y para los endpoints Referencia.
Códigos de Partida¶
Una partida se representa por una combinación de 4 caracteres alfanuméricos, excluyendo aquellas combinaciones consideradas ambigüas 1 2:
“O”, “0”
“I”, “1”
“B”, “8”
“2”, “Z”
Resultando en el siguiente set de caracteres, con el que se siguen teniendo \(28^4 = 614.656\) combinaciones, suficiente para lo que se necesita.
-
match.CODE_ALLOWED_CHARS= 'ACDEFGHJKLMNPQRSTUVWXY345679'¶
Creación de Partidas Privadas¶
Las partidas privadas son las más simples porque su inicio se realiza de forma manual con el líder.
Creación de Partidas Públicas¶
Las partidas públicas se administran de forma automática, por lo que el flujo es algo maś complejo. Se creará una partida para los jugadores que estén buscando una (con un timer que limite el tiempo de espera), y posteriormente tendrán que confirmar que se quieren unir (también con un timer para evitar esperas infinitas).
Transcurso de la Partida¶
Una vez la partida haya comenzado, el transcurso de la partida será el siguiente:
Abandono de la Partida¶
Se describe a continuación la funcionalidad de abandono y reconexión a las partidas:
El botón de abandonar es pulsado:
Pública: el jugador es eliminado y no se puede volver; el jugador es reemplazado por la IA.
El cliente tendrá que llamar a
leavemanualmente para ello.Privada: el jugador es eliminado y no se puede volver; las cartas del jugador van a la baraja.
El cliente tendrá que llamar a
leavemanualmente para ello.
Desconexión por error o botón de reanudar más tarde pulsado:
Pública: no se puede volver a jugar, se abandonará la partida automáticamente.
Privada: se puede volver a la partida y no habrá pasado nada porque en partidas privadas no se eliminan jugadores AFK.
Para volver únicamente hace falta llamar a
joincon el código de partida previo, y el cliente recibirá un start_game seguido de un game_update con el estado completo de la partida.
Advertencia
Notar que una desconexión puede causar que se cancele una partida, en cuyo
caso se enviará un mensaje de game_cancelled a todos los
participantes de esta. Es importante que el cliente salga de la partida
manualmente con leave una vez reciba dicho mensaje, o no podrá unirse
correctamente a otras partidas.
Mensajes Websockets¶
Para el correcto funcionamiento de la comunicación, es necesario el uso de la librería SocketIO en el cliente.
El nombre de los mensajes es el mismo que las funciones a contactar. Por
ejemplo, si se quiere contactar con el endpoint de create_game(), se debe
emitir un mensaje de tipo create_game.
Parámetros¶
El paso de parámetros será pasando directamente el valor en mensajes con solo un parámetro (y cuando no haya posibles parámetros opcionales), o con un objeto JSON cuando haya múltiples parámetros.
Los parámetros devueltos se ajustarán a las descripciones de return de cada endpoint.
Errores y Validación¶
Los errores de las peticiones serán devueltos al cliente llamando a un callback
definido en la función emit de SocketIO. Todos los errores estarán en formato
JSON, donde habrá un campo error: str que contendrá el mensaje de error
devuelto.
1 2 3 4 5 | socket.emit('join', dataToEmit, function (data) {
if (data && data.error) {
console.error(data.error);
}
});
|
Mensajes¶
Se listan en esta sección todos los tipos de mensajes, como referencia principal, para que se puedan serializar como objetos si se considera necesario:
create_game¶
{
// Código de la partida, compuesto por caracteres alfanuméricos, con las
// letras en mayúsculas.
"code": "A83D",
}
found_game¶
{
// Código de la partida, compuesto por caracteres alfanuméricos, con las
// letras en mayúsculas.
"code": "A83D",
}
users_waiting¶
Mensaje cuyo contenido es únicamente un entero con el número de usuarios esperando, incluido el mismo que lo haya recibido.
start_game¶
Mensaje sin campos adicionales.
game_owner¶
Mensaje sin campos adicionales.
game_cancelled¶
Mensaje sin campos adicionales.
stop_searching¶
Mensaje sin campos adicionales.
chat¶
{
// Mensaje enviado por el jugador
"msg": "Bona tarda",
// Nombre de usuario del jugador que envía el mensaje. Será
// ``[GATOVID]`` si es un mensaje del sistema, para indicar p.ej. que un
// usuario ha abandonado la partida.
"owner": "manolet22",
}
game_update¶
Como forma de optimización este tipo de mensaje no tiene por qué incluir todos los campos; solo se actualizará al frontend con lo que sea necesario.
{
// Terminación de la partida.
"finished": false,
// Lista de ganadores. Se incluye la posición de cada jugador, y las
// monedas que ha ganado por ello.
//
// Se mandará para indicar la terminación de la partida y la de un
// jugador individual, en cuyo caso `position` y `coins` serán nulos.
"leaderboard": {
"manolo22": {
"position": 1,
"coins": 50,
},
// ...
},
// Tiempo de juego en minutos.
"playtime_mins": 4,
// Nombre del usuario con el turno actual.
"current_turn": "manolo22",
// Información de los jugadores, enviada al inicio de la partida o
// cuando alguien abandone (y posiblemente sea reemplazado por la IA).
//
// Notar que el nombre de usuario no cambiará durante la partida. En el
// caso de que un usuario sea reemplazado por la IA el cliente le podría
// mostrar el nombre al usuario añadiendo "[BOT]" al final, o usar un
// icono indicativo, pero esto toma lugar en el frontend.
//
// IMPORTANTE: es posible que el mismo usuario que recibe el mensaje no
// aparezca en esta lista, lo que significa que ha sido eliminado de la
// partida por estar AFK o porque ha pulsado el botón de abandono. En
// caso de no encontrarse a sí mismo en este campo, el usuario tendrá
// que llamar al endpoint "leave" para abandonar la partida manualmente.
"players": [
{
"name": "marcuspkz",
// Verdadero si el usuario ha sido reemplazado por la IA.
// Opcional.
"is_ai": false,
// La foto puede cambiar si ha sido reemplazado por la IA.
// Opcional.
"picture": 4,
// El jugador que reciba el mensaje tendrá su tablero.
// Opcional.
"board": 2,
},
// ...
],
// Mano del jugador actual (solo él tendrá esa información).
"hand": [
{"card_type": "organ", "color": "red"},
{"card_type": "virus", "color": "green"},
{"card_type": "treatment", "treatment_type": "infection"},
],
// Los cuerpos de los jugadores.
"bodies": {
// Pila del jugador, siempre de longitud 4.
"marcuspkz": [
{
// Puede ser nulo si no hay nada en esa posición.
"organ": {
"card_type": "organ",
"color": "red"
}
// Puede estar vacío si no hay modificadores.
"modifiers": [
{"card_type": "virus", "color": "red"},
// ...
]
},
// ....
],
// ...
},
// Tiempo restante del timer del turno en segundos, para sincronizarlo
// con el cliente. Generalmente se enviará solo cuando se reconecte un
// jugador a la partida.
"remaining_turn_secs": 12.34,
}
Referencia¶
-
gatovid.api.game.chat(msg)¶ Enviar un mensaje al chat de la partida.
- Parámetros
msg (
str) – Mensaje a enviar- Devuelve
Broadcast de un mensaje chat.
Se borrarán en el mensaje todos los espacios anteriores y posteriores.
Si el usuario no está en una partida empezada se devolverá un error.
Se devolverá un error también en caso de que el mensaje supere la longitud máxima de caracteres establecida, o si es vacío tras quitar los espacios innecesarios:
-
game.MAX_CHAT_MSG_LEN= 240¶
-
-
gatovid.api.game.create_game()¶ Creación y unión automática a una partida privada.
- Devuelve
Un mensaje de tipo create_game.
Si está buscando una partida pública, se devolverá un error.
-
gatovid.api.game.join(game_code)¶ Unión a una partida proporcionando un código de partida.
Si se proporciona un código con minúsculas se intentará con el equivalente en mayúsculas.
- Parámetros
game_code (
str) – Código de partida- Devuelve
Si la partida es privada, un broadcast de users_waiting.
En cualquier caso, un broadcast de chat indicando que el jugador se ha unido a la partida.
Un jugador no se puede unir a una partida si ya está en otra o si ya está llena. En caso contrario se devolverá un error.
-
gatovid.api.game.leave()¶ Salir de la partida actual.
- Devuelve
Si la partida no se borra porque quedan jugadores:
Un mensaje de tipo users_waiting.
Un broadcast de chat indicando que el jugador ha abandonado la partida.
Si se ha delegado el cargo de líder, el nuevo líder recibirá un mensaje de tipo game_owner.
Si la partida se borra porque no quedan jugadores:
Si ya había terminado, un error.
Si no había terminado y se ha cancelado, un mensaje de tipo game_cancelled.
Requiere que el usuario esté en una partida o se devolverá un error.
-
gatovid.api.game.pause_game(paused)¶ Pausa o reanuda una partida privada.
- Parámetros
paused (
bool) – Pausar la partida
Requiere que el usuario esté en una partida privada y que esté empezada o se devolverá un error.
- Devuelve
Un mensaje game_update para cada jugador.
Si no se cumplen los requisitos comentados anteriormente, se devolverá un error.
-
gatovid.api.game.play_card(data)¶ Advertencia
Este endpoint está en construcción aún.
Juega una carta de su mano.
Requiere que el usuario esté en una partida y que esté empezada o se devolverá un error.
- Parámetros
data (Dict) –
Diccionario con datos sobre la carta a jugar. Todas las cartas deberán tener un campo
slot(int) con el slot de la carta jugada en la mano del jugador. Adicionalmente, algunas cartas en concreto tendrán parámetros específicos:- Órgano, Virus y Medicina:
target(str): nombre del jugador destinoorgan_pile(int): número de pila del jugador destino
- Tratamientos:
- Transplante:
target1(str): nombre de uno de los dos jugadores entre los que se intercambiarán los órganos.target2(str): nombre del otro jugador.organ_pile1(str): pila del jugador 1.organ_pile2(str): pila del jugador 2.
- Ladrón de Órganos:
target(str): nombre del jugador destino.organ_pile(int): pila del jugador destino.
- Error médico:
target(str): nombre del jugador destino
- Devuelve
Un mensaje game_update para cada jugador.
Si el usuario no está en una partida se devolverá un error.
-
gatovid.api.game.play_discard(card)¶ Descarta la carta indicada de la mano del usuario. Esta acción se puede repetir varias veces hasta que se pase el turno de forma automática o con
play_pass.La carta a descartar se puede indicar con el índice de ésta en su mano.
Requiere que el usuario esté en una partida y que esté empezada o se devolverá un error.
- Parámetros
card (int) – La carta del usuario a descartar
- Devuelve
Un mensaje game_update para cada jugador.
Si el usuario no está en una partida se devolverá un error. También se devolverá uno en caso de que el jugador no tenga cartas restantes para descartar o si la carta indicada no existe en la mano del jugador.
-
gatovid.api.game.play_pass()¶ Advertencia
Este endpoint está en construcción aún.
Pasa el turno del usuario.
Requiere que el usuario esté en una partida y que esté empezada o se devolverá un error.
- Devuelve
Un mensaje game_update para cada jugador.
Si el usuario no está en una partida se devolverá un error.
-
gatovid.api.game.search_game()¶ Unión a una partida pública organizada por el servidor.
- Devuelve
El cliente no recibirá respuesta hasta que el servidor haya encontrado oponentes contra los que jugar.
Una vez encontrada una partida, hará un broadcast de found_game.
Si ya está buscando partida, se devolverá un error.
-
gatovid.api.game.start_game()¶ Puesta en marcha de una partida privada.
- Devuelve
Un broadcast de start_game.
Requiere que el usuario esté en una partida y que sea el líder o se devolverá un error. También deben haber al menos 2 jugadores en total esperando la partida para empezarla.
-
gatovid.api.game.stop_searching()¶ Parar de buscar una partida pública organizada por el servidor.
- Devuelve
Devuelve un mensaje de tipo stop_searching si se ha podido cancelar la búsqueda.
Si se produce cualquier error (por ejemplo, que el usuario no esté buscando partida) se devolverá un error.
—
Anotaciones