Actualizar la funcion que maneja descartes
This commit is contained in:
parent
f4c0306717
commit
f325a586d3
@ -8,8 +8,8 @@ class Juego(val usuarios: ArrayList<Pair<String, Boolean>>) {
|
||||
private val cartas: Array<Int> = GestorJuegos.generarCartas()
|
||||
|
||||
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 estadoJuego = EstadoJuego.Espera
|
||||
private var posCartaActual = 10
|
||||
@ -17,55 +17,40 @@ class Juego(val usuarios: ArrayList<Pair<String, Boolean>>) {
|
||||
private var dragonPartida = Dragon.Negro
|
||||
private var oportunidadesRestantes = 0
|
||||
|
||||
suspend fun iniciarJuego(ws: WebSocketSession) {
|
||||
suspend fun iniciarJuego() {
|
||||
if (estadoJuego != EstadoJuego.Espera) return
|
||||
|
||||
if (conexiones.size < 4) {
|
||||
ws.send(Frame.Text("{\"operacion\": \"error\", \"razon\": \"Usuarios insuficientes\"}"))
|
||||
return
|
||||
}
|
||||
|
||||
estadoJuego = EstadoJuego.Iniciado
|
||||
|
||||
// Asignar orden de jugadores
|
||||
var i = 0
|
||||
val posInicio = (Math.random() * 4).toInt()
|
||||
conexiones.forEach { (idUsuario, _) ->
|
||||
ordenJugadores[i] = idUsuario
|
||||
val dragonActual = Dragon.get(i)
|
||||
val nuevoArrJugadores = Array<Jugador>(4) { JugadorBot(this, "-") }
|
||||
val jugadoresRestantes = arrayListOf(0, 1, 2, 3)
|
||||
|
||||
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>()
|
||||
|
||||
for (j in posCartaActual until (posCartaActual + 10)) {
|
||||
cartasL.add(cartas[j])
|
||||
}
|
||||
posCartaActual += 10
|
||||
|
||||
val mano = if (i == posInicio) {
|
||||
val sigCarta = cartas[posCartaActual]
|
||||
posCartaActual++
|
||||
gestorDora.actualizarDora()
|
||||
dragonPartida = dragonActual
|
||||
posJugadorActual = i
|
||||
|
||||
Mano(cartasL, sigCarta = sigCarta, dragon = dragonActual)
|
||||
} else {
|
||||
Mano(cartasL, dragon = dragonActual)
|
||||
jugador.inicializarCartas(cartasL)
|
||||
jugador.inicializarDragon(Dragon.get(i))
|
||||
jugador.send(Frame.Text("{\"operacion\": \"juego_iniciado\"}"))
|
||||
}
|
||||
|
||||
manos[idUsuario] = mano
|
||||
i++
|
||||
}
|
||||
|
||||
conexiones.forEach { (_, socket) ->
|
||||
socket.send(Frame.Text("{\"operacion\": \"juego_iniciado\"}"))
|
||||
}
|
||||
|
||||
conexiones.clear()
|
||||
jugadores = nuevoArrJugadores
|
||||
ordenJugadores = Array(4) { jugadores[it].idUsuario }
|
||||
}
|
||||
|
||||
private fun obtenerDatosJuegoActuales(): DatosJuego {
|
||||
val idJugadorTurnoActual = ordenJugadores[posJugadorActual]
|
||||
val idJugadorTurnoActual = jugadores[posJugadorActual].idUsuario
|
||||
return DatosJuego(
|
||||
dora = arrayListOf(),
|
||||
manos = hashMapOf(),
|
||||
@ -85,6 +70,8 @@ class Juego(val usuarios: ArrayList<Pair<String, Boolean>>) {
|
||||
}
|
||||
|
||||
suspend fun agregarConexion(idUsuario: String, conexion: WebSocketSession) {
|
||||
if (estadoJuego != EstadoJuego.Espera) return
|
||||
|
||||
// Buscar si el jugador ya existia
|
||||
jugadores.forEach {
|
||||
if (it.idUsuario == idUsuario) {
|
||||
@ -113,95 +100,33 @@ class Juego(val usuarios: ArrayList<Pair<String, Boolean>>) {
|
||||
posJugadorActual = (posJugadorActual + 1) % 4
|
||||
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]
|
||||
posCartaActual++
|
||||
|
||||
// Asignar nueva carta
|
||||
val manoSigJugador = manos[idSigUsuario]!!
|
||||
manoSigJugador.sigCarta = sigCarta
|
||||
|
||||
// TODO: Arreglar. Roto.
|
||||
val oportunidadWin = OportunidadWin.verificar(sigCarta, manoSigJugador.cartas, manoSigJugador.cartasReveladas)
|
||||
if (oportunidadWin != null) {
|
||||
manoSigJugador.oportunidades.add(oportunidadWin)
|
||||
// Asignar carta
|
||||
jugadores[posJugadorActual].recibirCarta(sigCarta)
|
||||
// Verificar Tsumo
|
||||
jugadores[posJugadorActual].verificarTsumo()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
suspend fun manejarDescarte(idUsuario: String, carta: Int) {
|
||||
if (ordenJugadores[posJugadorActual] != idUsuario) return
|
||||
suspend fun manejarDescarte(idUsuario: String, cartaDescartada: Int) {
|
||||
// Si un jugador del que no es turno intenta descartar
|
||||
if (jugadores[posJugadorActual].idUsuario != idUsuario) return
|
||||
|
||||
// Si el jugador del turno actual ya descarto, otros jugadores tienen oportunidades
|
||||
// e intento descartar de nuevo
|
||||
if (oportunidadesRestantes > 0) return
|
||||
|
||||
val m = manos[idUsuario]!!
|
||||
val cantidadOportunidades = jugadores[posJugadorActual].descartarCarta(cartaDescartada)
|
||||
|
||||
if (m.sigCarta == carta) {
|
||||
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) {
|
||||
if (cantidadOportunidades > 0) {
|
||||
// Enviar datos
|
||||
enviarDatosATodos()
|
||||
} else {
|
||||
|
@ -13,14 +13,75 @@ sealed class Jugador(val juego: Juego, val idUsuario: String) {
|
||||
abstract suspend fun send(v: Frame.Text)
|
||||
val mano = Mano()
|
||||
|
||||
fun inicializarMano(cartas: ArrayList<Int>) {
|
||||
fun inicializarCartas(cartas: ArrayList<Int>) {
|
||||
mano.cartas = cartas
|
||||
}
|
||||
|
||||
fun inicializarDragon(dragon: Dragon) {
|
||||
mano.dragon = dragon
|
||||
}
|
||||
|
||||
abstract fun actualizarConexion(ws: WebSocketSession)
|
||||
|
||||
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) {
|
||||
@ -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)}}"))
|
||||
}
|
||||
|
||||
override fun verificarTsumo() {
|
||||
System.err.println("Tsumo no implementado D:")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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:")
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ data class Mano(
|
||||
val descartes: ArrayList<Int> = arrayListOf(),
|
||||
var sigCarta: Int = -1,
|
||||
var oportunidades: ArrayList<Oportunidad> = arrayListOf(),
|
||||
val dragon: Dragon = Dragon.Negro
|
||||
var dragon: Dragon = Dragon.Negro
|
||||
) {
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user