2020-10-05 23:08:32 +00:00
|
|
|
package dev.araozu.juego
|
2020-09-21 21:25:21 +00:00
|
|
|
|
2020-10-05 23:08:32 +00:00
|
|
|
import dev.araozu.*
|
2020-09-23 01:20:23 +00:00
|
|
|
import io.ktor.http.cio.websocket.*
|
2020-09-21 21:25:21 +00:00
|
|
|
|
2020-09-23 01:20:23 +00:00
|
|
|
class Juego(val usuarios: ArrayList<Pair<String, Boolean>>) {
|
2020-09-21 21:25:21 +00:00
|
|
|
|
2020-09-23 01:20:23 +00:00
|
|
|
private val cartas: Array<Int> = GestorJuegos.generarCartas()
|
2020-09-23 02:11:15 +00:00
|
|
|
val conexiones: HashMap<String, WebSocketSession> = HashMap()
|
2020-09-25 19:41:02 +00:00
|
|
|
private val ordenJugadores = Array(4) { "" }
|
2020-09-23 01:20:23 +00:00
|
|
|
private val manos: HashMap<String, Mano> = HashMap()
|
2020-10-05 23:08:32 +00:00
|
|
|
private var gestorDora: GestorDora? = null
|
2020-09-25 15:10:08 +00:00
|
|
|
private var estadoJuego = EstadoJuego.Espera
|
|
|
|
private var posCartaActual = 0
|
2020-09-25 19:41:02 +00:00
|
|
|
private var turnoActual = 0
|
2020-09-21 21:25:21 +00:00
|
|
|
|
2020-09-23 02:11:15 +00:00
|
|
|
suspend fun iniciarJuego(ws: WebSocketSession) {
|
2020-09-23 01:20:23 +00:00
|
|
|
if (estadoJuego != EstadoJuego.Espera) return
|
2020-09-21 21:25:21 +00:00
|
|
|
|
2020-09-23 02:11:15 +00:00
|
|
|
if (conexiones.size < 4) {
|
|
|
|
ws.send(Frame.Text("{\"operacion\": \"error\", \"razon\": \"Usuarios insuficientes\"}"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-09-23 01:20:23 +00:00
|
|
|
estadoJuego = EstadoJuego.Iniciado
|
2020-10-05 23:08:32 +00:00
|
|
|
|
|
|
|
// Inicializar dora
|
|
|
|
val dora: ArrayList<Int> = arrayListOf()
|
2020-09-23 01:20:23 +00:00
|
|
|
for (i in posCartaActual until (posCartaActual + 10)) {
|
|
|
|
dora.add(cartas[i])
|
2020-09-21 21:25:21 +00:00
|
|
|
}
|
2020-10-05 23:08:32 +00:00
|
|
|
gestorDora = GestorDora(dora)
|
2020-09-23 01:20:23 +00:00
|
|
|
posCartaActual += 10
|
2020-09-21 21:25:21 +00:00
|
|
|
|
2020-09-25 15:10:08 +00:00
|
|
|
// Asignar orden de jugadores
|
|
|
|
var i = 0
|
|
|
|
var idJugadorInicial = ""
|
|
|
|
conexiones.forEach { (idUsuario, _) ->
|
|
|
|
if (i == 0) idJugadorInicial = idUsuario
|
|
|
|
ordenJugadores[i] = idUsuario
|
|
|
|
i++
|
|
|
|
|
2020-09-23 02:11:15 +00:00
|
|
|
val cartasL = arrayListOf<Int>()
|
2020-09-21 21:25:21 +00:00
|
|
|
|
2020-09-25 15:10:08 +00:00
|
|
|
for (j in posCartaActual until (posCartaActual + 10)) {
|
|
|
|
cartasL.add(cartas[j])
|
2020-09-23 01:20:23 +00:00
|
|
|
}
|
|
|
|
posCartaActual += 10
|
2020-09-21 21:25:21 +00:00
|
|
|
|
2020-09-25 15:10:08 +00:00
|
|
|
val mano = if (idJugadorInicial == idUsuario) {
|
|
|
|
val sigCarta = cartas[posCartaActual]
|
|
|
|
posCartaActual++
|
2020-10-06 01:44:58 +00:00
|
|
|
gestorDora!!.actualizarDoraCerrado()
|
2020-09-25 15:10:08 +00:00
|
|
|
|
|
|
|
Mano(cartasL, sigCarta = sigCarta)
|
|
|
|
} else {
|
|
|
|
Mano(cartasL)
|
|
|
|
}
|
|
|
|
|
2020-09-23 01:20:23 +00:00
|
|
|
manos[idUsuario] = mano
|
2020-09-21 21:25:21 +00:00
|
|
|
}
|
|
|
|
|
2020-09-25 15:10:08 +00:00
|
|
|
conexiones.forEach { (_, socket) ->
|
2020-09-23 01:20:23 +00:00
|
|
|
socket.send(Frame.Text("{\"operacion\": \"juego_iniciado\"}"))
|
2020-09-21 21:25:21 +00:00
|
|
|
}
|
2020-09-25 15:10:08 +00:00
|
|
|
|
2020-09-23 01:20:23 +00:00
|
|
|
conexiones.clear()
|
|
|
|
}
|
|
|
|
|
2020-09-23 20:51:45 +00:00
|
|
|
private suspend fun enviarDatos(idUsuario: String, ws: WebSocketSession) {
|
|
|
|
val manosS = HashMap<String, Mano>()
|
|
|
|
|
|
|
|
for ((idUsuarioAct, mano) in manos) {
|
|
|
|
if (idUsuarioAct == idUsuario) {
|
|
|
|
manosS[idUsuarioAct] = mano
|
|
|
|
} else {
|
|
|
|
manosS[idUsuarioAct] = mano.obtenerManoPrivada()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-25 15:10:08 +00:00
|
|
|
val idJugadorTurnoActual = ordenJugadores[turnoActual]
|
2020-10-05 23:08:32 +00:00
|
|
|
val (doraCerrado, doraAbierto) = gestorDora!!
|
2020-09-25 15:10:08 +00:00
|
|
|
val datosJuego = DatosJuego(
|
2020-10-05 23:08:32 +00:00
|
|
|
doraCerrado,
|
|
|
|
doraAbierto,
|
2020-09-25 15:10:08 +00:00
|
|
|
manosS,
|
2020-09-25 15:52:48 +00:00
|
|
|
108 - posCartaActual,
|
2020-09-25 15:10:08 +00:00
|
|
|
ordenJugadores,
|
2020-09-25 19:41:02 +00:00
|
|
|
idJugadorTurnoActual,
|
2020-10-05 23:08:32 +00:00
|
|
|
gestorDora!!.turnosRestantesDoraCerrado
|
2020-09-25 15:10:08 +00:00
|
|
|
)
|
2020-09-23 20:51:45 +00:00
|
|
|
ws.send(Frame.Text("{\"operacion\": \"actualizar_datos\", \"datos\": ${gson.toJson(datosJuego)}}"))
|
|
|
|
}
|
|
|
|
|
2020-10-06 01:44:58 +00:00
|
|
|
private suspend fun enviarDatosATodos() {
|
|
|
|
for ((idUsuario, ws) in conexiones) {
|
|
|
|
enviarDatos(idUsuario, ws)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-23 20:51:45 +00:00
|
|
|
suspend fun agregarConexion(idUsuario: String, conexion: WebSocketSession) {
|
2020-09-23 02:11:15 +00:00
|
|
|
conexiones[idUsuario] = conexion
|
2020-09-23 20:51:45 +00:00
|
|
|
if (estadoJuego == EstadoJuego.Iniciado) {
|
|
|
|
enviarDatos(idUsuario, conexion)
|
|
|
|
}
|
2020-09-23 01:20:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fun agregarUsuario(idUsuario: String) {
|
2020-09-23 20:51:45 +00:00
|
|
|
if (estadoJuego == EstadoJuego.Espera) usuarios.add(Pair(idUsuario, true))
|
2020-09-21 21:25:21 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 01:44:58 +00:00
|
|
|
private fun cambiarTurnoSigJugadorConsecutivo() {
|
|
|
|
// Extraer, dar sig carta al sig jugador, cambiar turno
|
|
|
|
turnoActual = (turnoActual + 1) % 4
|
|
|
|
val idSigUsuario = ordenJugadores[turnoActual]
|
|
|
|
val sigCarta = cartas[posCartaActual]
|
|
|
|
posCartaActual++
|
|
|
|
manos[idSigUsuario]!!.sigCarta = sigCarta
|
2020-10-05 21:15:32 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 16:58:51 +00:00
|
|
|
private fun esUsuarioIzq(idUsuarioIzq: String, idUsuario1: String): Boolean {
|
|
|
|
var posUsuario1 = 0
|
|
|
|
var posUsuarioIzq = 0
|
|
|
|
for ((posActual, idUsuario) in ordenJugadores.withIndex()) {
|
|
|
|
if (idUsuario == idUsuario1) posUsuario1 = posActual
|
|
|
|
if (idUsuario == idUsuarioIzq) posUsuarioIzq = posActual
|
|
|
|
}
|
|
|
|
return (posUsuarioIzq + 1) % 4 == posUsuario1
|
|
|
|
}
|
|
|
|
|
2020-09-25 19:41:02 +00:00
|
|
|
suspend fun manejarDescarte(idUsuario: String, carta: Int) {
|
|
|
|
if (ordenJugadores[turnoActual] == idUsuario) {
|
|
|
|
val m = manos[idUsuario]!!
|
|
|
|
|
|
|
|
if (m.sigCarta == carta) {
|
|
|
|
m.sigCarta = -1
|
|
|
|
} else {
|
|
|
|
val posCarta = m.cartas.indexOf(carta)
|
|
|
|
if (posCarta != -1) {
|
|
|
|
m.cartas.removeAt(posCarta)
|
2020-10-07 13:31:18 +00:00
|
|
|
|
|
|
|
// Tras llamar un Seq/Tri el jugador no tiene una carta adicional en su mano.
|
|
|
|
if (m.sigCarta != -1) m.cartas.add(m.sigCarta)
|
|
|
|
|
2020-09-25 19:41:02 +00:00
|
|
|
m.sigCarta = -1
|
|
|
|
} else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m.descartes.add(carta)
|
|
|
|
|
2020-10-05 21:15:32 +00:00
|
|
|
// Verificar seq/tri/quad/win
|
2020-10-06 01:44:58 +00:00
|
|
|
var hayOportunidades = false
|
2020-10-06 15:02:00 +00:00
|
|
|
for ((idUsuarioActual, mano) in manos) {
|
|
|
|
// No buscar oportunidades en el usuario que acaba de descartar.
|
|
|
|
if (idUsuarioActual == idUsuario) continue
|
|
|
|
|
2020-10-06 16:58:51 +00:00
|
|
|
// Solo verificar seq en el jugador a la derecha del que descarto
|
|
|
|
if (esUsuarioIzq(idUsuario, idUsuarioActual)) {
|
|
|
|
val oportunidadSeq = OportunidadSeq.verificar(carta, mano.cartas)
|
|
|
|
if (oportunidadSeq != null) {
|
|
|
|
hayOportunidades = true
|
|
|
|
mano.oportunidades.add(oportunidadSeq)
|
|
|
|
}
|
2020-10-06 01:44:58 +00:00
|
|
|
}
|
2020-10-05 21:15:32 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 01:44:58 +00:00
|
|
|
if (hayOportunidades) {
|
|
|
|
// Enviar datos
|
|
|
|
enviarDatosATodos()
|
|
|
|
} else {
|
|
|
|
cambiarTurnoSigJugadorConsecutivo()
|
2020-09-25 19:41:02 +00:00
|
|
|
|
2020-10-06 01:44:58 +00:00
|
|
|
// Actualizar dora
|
|
|
|
gestorDora!!.actualizarDoraCerrado()
|
2020-09-25 19:41:02 +00:00
|
|
|
|
2020-10-06 01:44:58 +00:00
|
|
|
// Enviar datos
|
|
|
|
enviarDatosATodos()
|
|
|
|
}
|
2020-09-25 19:41:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-06 17:48:13 +00:00
|
|
|
suspend fun ignorarOportunidadSeq(idUsuario: String) {
|
|
|
|
|
|
|
|
var aunHayOportunidades = false
|
|
|
|
for ((id, mano) in manos) {
|
|
|
|
// Eliminar oportunidad del usuario
|
|
|
|
if (id == idUsuario) {
|
|
|
|
mano.oportunidades = arrayListOf()
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Si algun otro jugador tiene una oportunidad
|
|
|
|
if (mano.oportunidades.isNotEmpty()) {
|
|
|
|
aunHayOportunidades = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Si no quedan oportunidades cambiar el turno al sig jugador
|
|
|
|
if (!aunHayOportunidades) {
|
|
|
|
cambiarTurnoSigJugadorConsecutivo()
|
|
|
|
gestorDora!!.actualizarDoraCerrado()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enviar los nuevos datos
|
|
|
|
enviarDatosATodos()
|
|
|
|
}
|
|
|
|
|
2020-10-07 02:30:05 +00:00
|
|
|
suspend fun manejarSeq(idUsuario: String, cartaDescartada: Int, combinacion: Pair<Int, Int>) {
|
|
|
|
|
|
|
|
val manoJugadorDescarte = manos[ordenJugadores[turnoActual]]!!
|
|
|
|
val descartesJ = manoJugadorDescarte.descartes
|
|
|
|
|
|
|
|
// La carta solicitada para robar es invalida
|
|
|
|
if (descartesJ[descartesJ.size - 1] != cartaDescartada) {
|
|
|
|
println("La carta a robar es invalida")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
descartesJ.removeAt(descartesJ.size - 1)
|
|
|
|
|
|
|
|
val manoRobador = manos[idUsuario]!!
|
|
|
|
val cartasRobador = manoRobador.cartas
|
|
|
|
val (vCarta1, vCarta2) = combinacion
|
|
|
|
|
|
|
|
// El jugador no tiene las cartas con las que formar seq
|
|
|
|
if (!cartasRobador.contains(vCarta1) || !cartasRobador.contains(vCarta2)) {
|
|
|
|
println("El jugador no tiene las cartas que dice que tiene: $vCarta1, $vCarta2")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Quitar cartas de la mano y moverlas a cartas reveladas
|
|
|
|
cartasRobador.remove(vCarta1)
|
|
|
|
cartasRobador.remove(vCarta2)
|
|
|
|
val seq = arrayListOf(cartaDescartada, vCarta1, vCarta2)
|
|
|
|
manoRobador.cartasReveladas.add(seq)
|
|
|
|
|
|
|
|
// Eliminar las oportunidades
|
|
|
|
manoRobador.oportunidades = arrayListOf()
|
|
|
|
|
|
|
|
// Cambiar turno al robador sin dar carta
|
|
|
|
turnoActual = (turnoActual + 1) % 4
|
|
|
|
gestorDora!!.actualizarDoraCerrado()
|
|
|
|
|
|
|
|
enviarDatosATodos()
|
|
|
|
}
|
|
|
|
|
2020-09-21 21:25:21 +00:00
|
|
|
}
|