Actualizar la funcion que maneja descartes

master
Araozu 2020-12-27 13:07:33 -05:00
parent f4c0306717
commit f325a586d3
3 changed files with 142 additions and 113 deletions

View File

@ -8,8 +8,8 @@ class Juego(val usuarios: ArrayList<Pair<String, Boolean>>) {
private val cartas: Array<Int> = GestorJuegos.generarCartas() private val cartas: Array<Int> = GestorJuegos.generarCartas()
internal var jugadores = Array<Jugador>(4) { JugadorBot(this, "Bot $it") } internal var jugadores = Array<Jugador>(4) { JugadorBot(this, "Bot $it") }
private var ordenJugadores = Array(4) { jugadores[it].idUsuario }
private val ordenJugadores = Array(4) { "" }
private var gestorDora = GestorDora(cartas) private var gestorDora = GestorDora(cartas)
private var estadoJuego = EstadoJuego.Espera private var estadoJuego = EstadoJuego.Espera
private var posCartaActual = 10 private var posCartaActual = 10
@ -17,55 +17,40 @@ class Juego(val usuarios: ArrayList<Pair<String, Boolean>>) {
private var dragonPartida = Dragon.Negro private var dragonPartida = Dragon.Negro
private var oportunidadesRestantes = 0 private var oportunidadesRestantes = 0
suspend fun iniciarJuego(ws: WebSocketSession) { suspend fun iniciarJuego() {
if (estadoJuego != EstadoJuego.Espera) return if (estadoJuego != EstadoJuego.Espera) return
if (conexiones.size < 4) {
ws.send(Frame.Text("{\"operacion\": \"error\", \"razon\": \"Usuarios insuficientes\"}"))
return
}
estadoJuego = EstadoJuego.Iniciado estadoJuego = EstadoJuego.Iniciado
// Asignar orden de jugadores val nuevoArrJugadores = Array<Jugador>(4) { JugadorBot(this, "-") }
var i = 0 val jugadoresRestantes = arrayListOf(0, 1, 2, 3)
val posInicio = (Math.random() * 4).toInt()
conexiones.forEach { (idUsuario, _) ->
ordenJugadores[i] = idUsuario
val dragonActual = Dragon.get(i)
for (i in 0 until 4) {
val nuevoIndice = (Math.random() * jugadoresRestantes.size).toInt()
nuevoArrJugadores[i] = jugadores[nuevoIndice]
jugadoresRestantes.remove(nuevoIndice)
}
dragonPartida = Dragon.get((Math.random() * 4).toInt())
for ((i, jugador) in nuevoArrJugadores.withIndex()) {
val cartasL = arrayListOf<Int>() val cartasL = arrayListOf<Int>()
for (j in posCartaActual until (posCartaActual + 10)) { for (j in posCartaActual until (posCartaActual + 10)) {
cartasL.add(cartas[j]) cartasL.add(cartas[j])
} }
posCartaActual += 10 posCartaActual += 10
val mano = if (i == posInicio) { jugador.inicializarCartas(cartasL)
val sigCarta = cartas[posCartaActual] jugador.inicializarDragon(Dragon.get(i))
posCartaActual++ jugador.send(Frame.Text("{\"operacion\": \"juego_iniciado\"}"))
gestorDora.actualizarDora()
dragonPartida = dragonActual
posJugadorActual = i
Mano(cartasL, sigCarta = sigCarta, dragon = dragonActual)
} else {
Mano(cartasL, dragon = dragonActual)
}
manos[idUsuario] = mano
i++
} }
conexiones.forEach { (_, socket) -> jugadores = nuevoArrJugadores
socket.send(Frame.Text("{\"operacion\": \"juego_iniciado\"}")) ordenJugadores = Array(4) { jugadores[it].idUsuario }
}
conexiones.clear()
} }
private fun obtenerDatosJuegoActuales(): DatosJuego { private fun obtenerDatosJuegoActuales(): DatosJuego {
val idJugadorTurnoActual = ordenJugadores[posJugadorActual] val idJugadorTurnoActual = jugadores[posJugadorActual].idUsuario
return DatosJuego( return DatosJuego(
dora = arrayListOf(), dora = arrayListOf(),
manos = hashMapOf(), manos = hashMapOf(),
@ -85,6 +70,8 @@ class Juego(val usuarios: ArrayList<Pair<String, Boolean>>) {
} }
suspend fun agregarConexion(idUsuario: String, conexion: WebSocketSession) { suspend fun agregarConexion(idUsuario: String, conexion: WebSocketSession) {
if (estadoJuego != EstadoJuego.Espera) return
// Buscar si el jugador ya existia // Buscar si el jugador ya existia
jugadores.forEach { jugadores.forEach {
if (it.idUsuario == idUsuario) { if (it.idUsuario == idUsuario) {
@ -113,95 +100,33 @@ class Juego(val usuarios: ArrayList<Pair<String, Boolean>>) {
posJugadorActual = (posJugadorActual + 1) % 4 posJugadorActual = (posJugadorActual + 1) % 4
oportunidadesRestantes = 0 oportunidadesRestantes = 0
val idSigUsuario = ordenJugadores[posJugadorActual] // Si se acabaron las cartas
if (posCartaActual >= cartas.size) {
estadoJuego = EstadoJuego.Terminado
return
}
// Extraer sig carta. TODO: Verificar que no quedan cartas y establecer empate // Sino
val sigCarta = cartas[posCartaActual] val sigCarta = cartas[posCartaActual]
posCartaActual++ posCartaActual++
// Asignar nueva carta // Asignar carta
val manoSigJugador = manos[idSigUsuario]!! jugadores[posJugadorActual].recibirCarta(sigCarta)
manoSigJugador.sigCarta = sigCarta // Verificar Tsumo
jugadores[posJugadorActual].verificarTsumo()
// TODO: Arreglar. Roto.
val oportunidadWin = OportunidadWin.verificar(sigCarta, manoSigJugador.cartas, manoSigJugador.cartasReveladas)
if (oportunidadWin != null) {
manoSigJugador.oportunidades.add(oportunidadWin)
}
} }
private fun esUsuarioIzq(idUsuarioIzq: String, idUsuario1: String): Boolean { suspend fun manejarDescarte(idUsuario: String, cartaDescartada: Int) {
var posUsuario1 = 0 // Si un jugador del que no es turno intenta descartar
var posUsuarioIzq = 0 if (jugadores[posJugadorActual].idUsuario != idUsuario) return
for ((posActual, idUsuario) in ordenJugadores.withIndex()) {
if (idUsuario == idUsuario1) posUsuario1 = posActual
if (idUsuario == idUsuarioIzq) posUsuarioIzq = posActual
}
return (posUsuarioIzq + 1) % 4 == posUsuario1
}
suspend fun manejarDescarte(idUsuario: String, carta: Int) {
if (ordenJugadores[posJugadorActual] != idUsuario) return
// Si el jugador del turno actual ya descarto, otros jugadores tienen oportunidades // Si el jugador del turno actual ya descarto, otros jugadores tienen oportunidades
// e intento descartar de nuevo // e intento descartar de nuevo
if (oportunidadesRestantes > 0) return if (oportunidadesRestantes > 0) return
val m = manos[idUsuario]!! val cantidadOportunidades = jugadores[posJugadorActual].descartarCarta(cartaDescartada)
if (m.sigCarta == carta) { if (cantidadOportunidades > 0) {
m.sigCarta = -1
} else {
val posCarta = m.cartas.indexOf(carta)
if (posCarta != -1) {
m.cartas.removeAt(posCarta)
// Tras llamar un Seq/Tri el jugador no tiene una carta adicional en su mano.
if (m.sigCarta != -1) m.cartas.add(m.sigCarta)
m.sigCarta = -1
} else {
return
}
}
m.descartes.add(carta)
// Verificar seq/tri/win
var hayOportunidades = false
for ((idUsuarioActual, mano) in manos) {
// No buscar oportunidades en el usuario que acaba de descartar.
if (idUsuarioActual == idUsuario) continue
// 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
oportunidadesRestantes++
mano.oportunidades.add(oportunidadSeq)
}
}
// Oportunidades tri
val oportunidadTri = OportunidadTri.verificar(carta, mano.cartas)
if (oportunidadTri != null) {
hayOportunidades = true
oportunidadesRestantes++
mano.oportunidades.add(oportunidadTri)
}
// Oportunidades win (ron)
val oportunidadWin = OportunidadWin.verificar(carta, mano.cartas, mano.cartasReveladas)
if (oportunidadWin != null) {
hayOportunidades = true
oportunidadesRestantes++
mano.oportunidades.add(oportunidadWin)
}
}
if (hayOportunidades) {
// Enviar datos // Enviar datos
enviarDatosATodos() enviarDatosATodos()
} else { } else {

View File

@ -13,14 +13,75 @@ sealed class Jugador(val juego: Juego, val idUsuario: String) {
abstract suspend fun send(v: Frame.Text) abstract suspend fun send(v: Frame.Text)
val mano = Mano() val mano = Mano()
fun inicializarMano(cartas: ArrayList<Int>) { fun inicializarCartas(cartas: ArrayList<Int>) {
mano.cartas = cartas mano.cartas = cartas
} }
fun inicializarDragon(dragon: Dragon) {
mano.dragon = dragon
}
abstract fun actualizarConexion(ws: WebSocketSession) abstract fun actualizarConexion(ws: WebSocketSession)
abstract suspend fun enviarDatos(datos: DatosJuego) abstract suspend fun enviarDatos(datos: DatosJuego)
fun recibirCarta(carta: Int) {
mano.sigCarta = carta
}
/**
* Intenta descartar una carta de la mano y devuelve si dicho descarte
* brinda oportunidades a otros jugadores
* @param cartaDescartada La carta a remover de la mano
* @return La cantidad de oportunidades
*/
fun descartarCarta(cartaDescartada: Int): Int {
val cartaFueDescartada = mano.descartarCarta(cartaDescartada)
if (!cartaFueDescartada) return -1
var oportunidadesRestantes = 0
var posicionJugadorActual = -1
for ((i, jugador) in juego.jugadores.withIndex()) {
if (this === jugador) {
posicionJugadorActual = i
continue
}
var hayOportunidad = false
val mano = jugador.mano
// Verificar seq en jugador a la derecha
if ((posicionJugadorActual + 1) % 4 == i) {
val oportunidadSeq = OportunidadSeq.verificar(cartaDescartada, mano.cartas)
if (oportunidadSeq != null) {
hayOportunidad = true
mano.oportunidades.add(oportunidadSeq)
}
}
// Oportunidades tri
val oportunidadTri = OportunidadTri.verificar(cartaDescartada, mano.cartas)
if (oportunidadTri != null) {
hayOportunidad = true
mano.oportunidades.add(oportunidadTri)
}
// Oportunidades win (ron)
val oportunidadWin = OportunidadWin.verificar(cartaDescartada, mano.cartas, mano.cartasReveladas)
if (oportunidadWin != null) {
hayOportunidad = true
mano.oportunidades.add(oportunidadWin)
}
if (hayOportunidad) oportunidadesRestantes++
}
return oportunidadesRestantes
}
abstract fun verificarTsumo()
} }
class JugadorHumano(juego: Juego, idUsuario: String, private var ws: WebSocketSession) : Jugador(juego, idUsuario) { class JugadorHumano(juego: Juego, idUsuario: String, private var ws: WebSocketSession) : Jugador(juego, idUsuario) {
@ -53,6 +114,10 @@ class JugadorHumano(juego: Juego, idUsuario: String, private var ws: WebSocketSe
ws.send(Frame.Text("{\"operacion\": \"actualizar_datos\", \"datos\": ${gson.toJson(datosJuego)}}")) ws.send(Frame.Text("{\"operacion\": \"actualizar_datos\", \"datos\": ${gson.toJson(datosJuego)}}"))
} }
override fun verificarTsumo() {
System.err.println("Tsumo no implementado D:")
}
} }
class JugadorBot(juego: Juego, idUsuario: String) : Jugador(juego, idUsuario) { class JugadorBot(juego: Juego, idUsuario: String) : Jugador(juego, idUsuario) {
@ -77,4 +142,8 @@ class JugadorBot(juego: Juego, idUsuario: String) : Jugador(juego, idUsuario) {
} }
override fun verificarTsumo() {
System.err.println("Tsumo no implementado D:")
}
} }

View File

@ -6,7 +6,7 @@ data class Mano(
val descartes: ArrayList<Int> = arrayListOf(), val descartes: ArrayList<Int> = arrayListOf(),
var sigCarta: Int = -1, var sigCarta: Int = -1,
var oportunidades: ArrayList<Oportunidad> = arrayListOf(), var oportunidades: ArrayList<Oportunidad> = arrayListOf(),
val dragon: Dragon = Dragon.Negro var dragon: Dragon = Dragon.Negro
) { ) {
fun obtenerManoPrivada(): Mano { fun obtenerManoPrivada(): Mano {
@ -19,6 +19,41 @@ data class Mano(
) )
} }
private fun validarHay10Cartas(): Boolean =
cartas.size + (cartasReveladas.size * 3) + (if (sigCarta != -1) 1 else 0) - 1 == 10
/**
* Intenta descartar una carta de la mano y devuelve si fue correcto
* @param cartaDescartada La carta a remover de la mano
* @return true si se descarto la carta, false sino
*/
fun descartarCarta(cartaDescartada: Int): Boolean {
if (!validarHay10Cartas()) {
System.err.println("Error al descartar carta: Hacerlo dejaria al jugador con menos de 10 cartas")
return false
}
if (sigCarta == cartaDescartada) {
sigCarta = -1
} else {
val posCarta = cartas.indexOf(cartaDescartada)
if (posCarta != -1) {
cartas.removeAt(posCarta)
// Incluir la carta entrante a la mano del jugador
if (sigCarta != -1) {
cartas.add(sigCarta)
}
} else {
System.err.println("Error al descartar carta: El jugador no tiene dicha carta.")
return false
}
}
descartes.add(cartaDescartada)
return true
}
// TODO: Cachear la mano privada y actualizarla solo cuando se llama tri/seq
} }