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()
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)
}
manos[idUsuario] = mano
i++
jugador.inicializarCartas(cartasL)
jugador.inicializarDragon(Dragon.get(i))
jugador.send(Frame.Text("{\"operacion\": \"juego_iniciado\"}"))
}
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 {

View File

@ -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:")
}
}

View File

@ -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
}