Compare commits

...

10 Commits

Author SHA1 Message Date
Araozu 8f9f0d8c5d Add jenkinsfile & dockerfile 2024-05-06 13:44:21 -05:00
Araozu 40ff1d67bc Modificar yaku Triple Triples Cerrado 2020-12-31 12:07:20 -05:00
Araozu b84531f66a Implementar Ron 2020-12-31 09:24:20 -05:00
Araozu 8c58639a61 Modificar Yaku 2020-12-31 08:20:22 -05:00
Araozu 2f0305d4c2 Reescalar frecuencia de Dora de 20 15 10 5 a 31 15 7 3 2020-12-29 09:18:48 -05:00
Araozu 5856c730e8 Agregar pruebas a Yaku1, 2 y 3 2020-12-29 08:25:51 -05:00
Araozu 7cb9b16f23 Arreglar error al verificar Ron en manos con grupos abiertos 2020-12-29 08:21:59 -05:00
Araozu b02afac301 Agregar pruebas a los yaku 2020-12-28 11:05:06 -05:00
Araozu 64c802ad85 Modificar y corregir yaku 2020-12-28 11:04:05 -05:00
Araozu 1ddb05a55d Agregar un delay aleatorio de 1-5s a las acciones de los bots 2020-12-28 11:03:39 -05:00
30 changed files with 663 additions and 184 deletions

7
Dockerfile Normal file
View File

@ -0,0 +1,7 @@
FROM eclipse-temurin:11
EXPOSE 8080:8080
# When this is run, Jenkins has already built the FAT JAR
RUN mkdir /app
COPY ./build/libs/rimajon-0.0.1-all.jar /app/backend.jar
ENTRYPOINT ["java","-jar","/app/backend.jar"]

20
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,20 @@
pipeline {
agent {
docker {
image "gradle:7.6.4-jdk11"
}
}
stages {
stage('Build FAT JAR') {
steps {
sh 'gradle shadowJar'
}
}
stage("Deploy jar") {
steps {
sh "echo ':D (need to spin up container)'"
}
}
}
}

View File

@ -8,6 +8,10 @@ buildscript {
} }
} }
plugins {
id 'com.github.johnrengelman.shadow' version '7.0.0'
}
apply plugin: 'kotlin' apply plugin: 'kotlin'
apply plugin: 'application' apply plugin: 'application'
@ -28,6 +32,12 @@ repositories {
maven { url 'https://kotlin.bintray.com/ktor' } maven { url 'https://kotlin.bintray.com/ktor' }
} }
shadowJar {
manifest {
attributes 'Main-Class': 'com.example.ApplicationKt'
}
}
dependencies { dependencies {
compile("org.jetbrains.exposed:exposed-core:0.24.1") compile("org.jetbrains.exposed:exposed-core:0.24.1")
compile("org.jetbrains.exposed:exposed-dao:0.24.1") compile("org.jetbrains.exposed:exposed-dao:0.24.1")
@ -40,4 +50,5 @@ dependencies {
implementation "io.ktor:ktor-gson:$ktor_version" implementation "io.ktor:ktor-gson:$ktor_version"
implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.google.code.gson:gson:2.8.5'
testImplementation "io.ktor:ktor-server-tests:$ktor_version" testImplementation "io.ktor:ktor-server-tests:$ktor_version"
// testImplementation 'io.kotest:kotest-runner-junit5:$version'
} }

6
docker-compose.yml Normal file
View File

@ -0,0 +1,6 @@
services:
web:
build: .
ports:
- "9124:8080"

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: dev.araozu.ApplicationKt

View File

@ -89,9 +89,18 @@ object GestorJuegos {
juego.ignorarOportunidades(idUsuario) juego.ignorarOportunidades(idUsuario)
} }
suspend fun manejarLlamarSeq(idJuego: String, idUsuario: String, cartaDescartada: Int, combinacion: Pair<Int, Int>) { suspend fun manejarLlamarSeq(
idJuego: String,
idUsuario: String,
cartaDescartada: Int,
combinacion: Pair<Int, Int>
) {
val juego = juegos[idJuego]!! val juego = juegos[idJuego]!!
juego.manejarSeqTri(idUsuario, cartaDescartada, combinacion) juego.manejarSeqTri(idUsuario, cartaDescartada, combinacion)
} }
suspend fun manejarRon(idJuego: String, idUsuario: String) {
juegos[idJuego]!!.manejarRon(idUsuario)
}
} }

View File

@ -46,13 +46,17 @@ fun Routing.juegows() {
) )
} }
"llamar_ron" -> { "llamar_ron" -> {
TODO() val datos = gson.fromJson(sol.datos, DatosIgnorarOportunidad::class.java)
GestorJuegos.manejarRon(datos.idJuego, datos.idUsuario)
} }
"llamar_tsumo" -> { "llamar_tsumo" -> {
TODO() TODO("Tsumo no implementado")
} }
} }
} }
else -> {
System.err.println("Tipo de dato enviado al socket no admitido")
}
} }
} }

View File

@ -12,8 +12,7 @@ class ContenedorGrupos(
arrayListOf<ArrayList<Carta>>(), arrayListOf<ArrayList<Carta>>(),
arrayListOf<ArrayList<Carta>>(), arrayListOf<ArrayList<Carta>>(),
arrayListOf<Carta>() arrayListOf<Carta>()
) { )
}
fun agregarDesdeContenedor(c: ContenedorGrupos) { fun agregarDesdeContenedor(c: ContenedorGrupos) {
tris.addAll(c.tris) tris.addAll(c.tris)

View File

@ -8,7 +8,7 @@ data class DatosJuego(
val turnoActual: String, val turnoActual: String,
val turnosHastaDora: Int, val turnosHastaDora: Int,
val dragonPartida: Dragon, val dragonPartida: Dragon,
val oportunidadesRestantes: Int val estadoJuego: EstadoJuego
) { ) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
@ -23,7 +23,7 @@ data class DatosJuego(
if (turnoActual != other.turnoActual) return false if (turnoActual != other.turnoActual) return false
if (turnosHastaDora != other.turnosHastaDora) return false if (turnosHastaDora != other.turnosHastaDora) return false
if (dragonPartida != other.dragonPartida) return false if (dragonPartida != other.dragonPartida) return false
if (oportunidadesRestantes != other.oportunidadesRestantes) return false if (estadoJuego != other.estadoJuego) return false
return true return true
} }
@ -36,7 +36,7 @@ data class DatosJuego(
result = 31 * result + turnoActual.hashCode() result = 31 * result + turnoActual.hashCode()
result = 31 * result + turnosHastaDora result = 31 * result + turnosHastaDora
result = 31 * result + dragonPartida.hashCode() result = 31 * result + dragonPartida.hashCode()
result = 31 * result + oportunidadesRestantes result = 31 * result + estadoJuego.hashCode()
return result return result
} }
} }

View File

@ -4,8 +4,8 @@ class GestorDora(cartasIniciales: Array<Int>) {
private val cartas = Array(5) { -1 } private val cartas = Array(5) { -1 }
val dora: ArrayList<Int> val dora: ArrayList<Int>
private var turnosSigDora = 20 private var turnosSigDora = 31 // 31 15 7 3
var turnosRestantesDora = turnosSigDora // 20 15 10 5 var turnosRestantesDora = turnosSigDora
private set private set
init { init {
@ -25,7 +25,7 @@ class GestorDora(cartasIniciales: Array<Int>) {
if (turnosRestantesDora == 0) { if (turnosRestantesDora == 0) {
dora.add(cartas[dora.size]) dora.add(cartas[dora.size])
turnosSigDora -= 5 turnosSigDora = (turnosSigDora - 1) / 2
turnosRestantesDora = turnosSigDora turnosRestantesDora = turnosSigDora
} }

View File

@ -78,7 +78,7 @@ class Juego(val idJuego: String) {
turnoActual = idJugadorTurnoActual, turnoActual = idJugadorTurnoActual,
turnosHastaDora = gestorDora.turnosRestantesDora, turnosHastaDora = gestorDora.turnosRestantesDora,
dragonPartida = dragonPartida, dragonPartida = dragonPartida,
oportunidadesRestantes = oportunidadesRestantes estadoJuego = estadoJuego
) )
} }
@ -208,4 +208,15 @@ class Juego(val idJuego: String) {
enviarDatosATodos() enviarDatosATodos()
} }
suspend fun manejarRon(idUsuario: String) {
val jugadorRon = jugadores.find { it.idUsuario == idUsuario } ?: return
val ronExitoso = jugadorRon.manejarRon()
if (!ronExitoso) return
estadoJuego = EstadoJuego.Terminado
enviarDatosATodos()
}
} }

View File

@ -69,10 +69,10 @@ sealed class Jugador(val juego: Juego, val idUsuario: String) {
} }
// Oportunidades win (ron) // Oportunidades win (ron)
val oportunidadWin = OportunidadWin.verificar(cartaDescartada, mano.cartas, mano.cartasReveladas) val oportunidadRon = OportunidadRon.verificar(cartaDescartada, mano.cartas, mano.cartasReveladas)
if (oportunidadWin != null) { if (oportunidadRon != null) {
hayOportunidad = true hayOportunidad = true
mano.oportunidades.add(oportunidadWin) mano.oportunidades.add(oportunidadRon)
} }
if (hayOportunidad) oportunidadesRestantes++ if (hayOportunidad) oportunidadesRestantes++
@ -121,6 +121,16 @@ sealed class Jugador(val juego: Juego, val idUsuario: String) {
return true return true
} }
fun manejarRon(): Boolean {
mano.oportunidades.find { it is OportunidadRon } ?: return false
// Limpiar oportunidades
mano.oportunidades.clear()
mano.esGanador = true
return true
}
private fun ultimaCartaDescartadaEs(carta: Int): Boolean = private fun ultimaCartaDescartadaEs(carta: Int): Boolean =
mano.descartes[mano.descartes.size - 1] == carta mano.descartes[mano.descartes.size - 1] == carta
@ -175,21 +185,20 @@ class JugadorBot(juego: Juego, idUsuario: String) : Jugador(juego, idUsuario) {
private val mutexOportunidad = Mutex() private val mutexOportunidad = Mutex()
override suspend fun send(v: Frame.Text) { override suspend fun send(v: Frame.Text) {
println("Datos enviados a bot, pero ignorados.")
} }
override fun actualizarConexion(ws: WebSocketSession) {} override fun actualizarConexion(ws: WebSocketSession) {}
override suspend fun enviarDatos(datos: DatosJuego) { override suspend fun enviarDatos(datos: DatosJuego) {
println("Bot $idUsuario pensando")
// Si el bot tiene una carta adicional // Si el bot tiene una carta adicional
if (mano.sigCarta != -1) { if (mano.sigCarta != -1) {
// Espera 1s y la descarta // Espera 1s y la descarta
GlobalScope.launch { GlobalScope.launch {
mutexDescarte.lock() mutexDescarte.lock()
delay(1000) delay((Math.random() * 5 + 1).toLong() * 1000)
println("Bot $idUsuario descartando la carta que recibio (${mano.sigCarta})")
juego.manejarDescarte(idUsuario, mano.sigCarta) juego.manejarDescarte(idUsuario, mano.sigCarta)
mutexDescarte.unlock() mutexDescarte.unlock()
} }
@ -200,8 +209,8 @@ class JugadorBot(juego: Juego, idUsuario: String) : Jugador(juego, idUsuario) {
// Espera 1s e ignora oportunidades // Espera 1s e ignora oportunidades
GlobalScope.launch { GlobalScope.launch {
mutexOportunidad.lock() mutexOportunidad.lock()
delay(1000) delay((Math.random() * 5 + 1).toLong() * 1000)
println("Bot $idUsuario ignorando sus oportunidades (${mano.oportunidades.size}")
juego.ignorarOportunidades(idUsuario) juego.ignorarOportunidades(idUsuario)
mutexOportunidad.unlock() mutexOportunidad.unlock()
} }
@ -210,7 +219,7 @@ class JugadorBot(juego: Juego, idUsuario: String) : Jugador(juego, idUsuario) {
} }
override fun verificarTsumo() { override fun verificarTsumo() {
System.err.println("Tsumo no implementado D:")
} }
} }

View File

@ -6,10 +6,13 @@ 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(),
var dragon: Dragon = Dragon.Negro var dragon: Dragon = Dragon.Negro,
var esGanador: Boolean = false
) { ) {
fun obtenerManoPrivada(): Mano { fun obtenerManoPrivada(): Mano {
if (esGanador) return this
val l = ArrayList<Int>() val l = ArrayList<Int>()
l.addAll(cartas.map { 0 }) l.addAll(cartas.map { 0 })
return this.copy( return this.copy(

View File

@ -3,7 +3,7 @@ package dev.araozu.juego
import dev.araozu.juego.yaku.Yaku import dev.araozu.juego.yaku.Yaku
import dev.araozu.juego.yaku.obtenerListaYakus import dev.araozu.juego.yaku.obtenerListaYakus
class OportunidadWin(override val cartaDescartada: Int, val yaku: ArrayList<Yaku>) : Oportunidad { class OportunidadRon(override val cartaDescartada: Int, val yaku: ArrayList<Yaku>) : Oportunidad {
override val nombreOportunidad = "Win" override val nombreOportunidad = "Win"
@ -148,7 +148,11 @@ class OportunidadWin(override val cartaDescartada: Int, val yaku: ArrayList<Yaku
return if (valorCont1 > valorCont2) contenedor1 else contenedor2 return if (valorCont1 > valorCont2) contenedor1 else contenedor2
} }
fun verificar(valorCarta: Int, cartasMano: ArrayList<Int>, gruposAbiertos: ArrayList<ArrayList<Int>>): OportunidadWin? { fun verificar(
valorCarta: Int,
cartasMano: ArrayList<Int>,
gruposAbiertos: ArrayList<ArrayList<Int>> = arrayListOf()
): OportunidadRon? {
val narrl = ArrayList<Int>(cartasMano.size + 1) val narrl = ArrayList<Int>(cartasMano.size + 1)
narrl.addAll(cartasMano) narrl.addAll(cartasMano)
narrl.add(valorCarta) narrl.add(valorCarta)
@ -170,9 +174,7 @@ class OportunidadWin(override val cartaDescartada: Int, val yaku: ArrayList<Yaku
contenedorGrupos.agregarDesdeContenedor(obtenerContenedorCartasNumero(cartasRojo)) contenedorGrupos.agregarDesdeContenedor(obtenerContenedorCartasNumero(cartasRojo))
contenedorGrupos.agregarDesdeContenedor(obtenerContenedorCartasNumero(cartasNegro)) contenedorGrupos.agregarDesdeContenedor(obtenerContenedorCartasNumero(cartasNegro))
if (!contenedorGrupos.estaListo()) return null val esManoAbierta = gruposAbiertos.isNotEmpty()
val esManoAbierta = gruposAbiertos.isEmpty()
if (esManoAbierta) { if (esManoAbierta) {
// Agregar los grupos abiertos al contenedor // Agregar los grupos abiertos al contenedor
@ -188,10 +190,12 @@ class OportunidadWin(override val cartaDescartada: Int, val yaku: ArrayList<Yaku
} }
} }
if (!contenedorGrupos.estaListo()) return null
// Obtener yaku // Obtener yaku
val yaku = obtenerListaYakus(contenedorGrupos, esManoAbierta) val yaku = obtenerListaYakus(contenedorGrupos, esManoAbierta)
return if (yaku.isNotEmpty()) OportunidadWin(valorCarta, yaku) else null return if (yaku.isNotEmpty()) OportunidadRon(valorCarta, yaku) else null
} }
} }

View File

@ -3,34 +3,37 @@ package dev.araozu.juego.yaku
import dev.araozu.juego.ContenedorGrupos import dev.araozu.juego.ContenedorGrupos
enum class Yaku { enum class Yaku {
// 15 // 10
DragonesFull, DragonesFull,
Verde, Verde,
// 10 // 7
RealezaDragones, RealezaDragones,
RealezaFull, RealezaFull,
EscaleraPerfecta,
A10,
// 5 // 5
TripleTriplesCerrados,
EscaleraFull, EscaleraFull,
// 3
TripleTriplesCerrados,
Exterior, Exterior,
// 4 // 2
Escalera, Escalera,
TripleCuadruples,
Negro, Negro,
Rojo, Rojo,
SemiExterior, SemiExterior,
DobleSecuenciaPura,
// 3 // 1
ParUnico,
Dragones, Dragones,
Interior, Interior,
TripleTriples, TripleTriples,
TripleSecuenciaCerrada,
Realeza, Realeza,
DobleSecuenciaPura DobleSecuencia,
ManoCerrada
} }
fun obtenerListaYakus(contenedorGrupos: ContenedorGrupos, esManoAbierta: Boolean): ArrayList<Yaku> { fun obtenerListaYakus(contenedorGrupos: ContenedorGrupos, esManoAbierta: Boolean): ArrayList<Yaku> {
@ -45,7 +48,7 @@ fun obtenerListaYakus(contenedorGrupos: ContenedorGrupos, esManoAbierta: Boolean
return arrayListOf() return arrayListOf()
} }
// 15 puntos // 10 puntos
if (yakuDragonesFull(contenedorGrupos)) { if (yakuDragonesFull(contenedorGrupos)) {
listaYakus.add(Yaku.DragonesFull) listaYakus.add(Yaku.DragonesFull)
return listaYakus return listaYakus
@ -55,7 +58,7 @@ fun obtenerListaYakus(contenedorGrupos: ContenedorGrupos, esManoAbierta: Boolean
return listaYakus return listaYakus
} }
// 10 puntos // 7 puntos
if (yakuRealezaDragones(contenedorGrupos)) { if (yakuRealezaDragones(contenedorGrupos)) {
listaYakus.add(Yaku.RealezaDragones) listaYakus.add(Yaku.RealezaDragones)
return listaYakus return listaYakus
@ -66,6 +69,9 @@ fun obtenerListaYakus(contenedorGrupos: ContenedorGrupos, esManoAbierta: Boolean
} }
// 5 puntos // 5 puntos
// TODO
// 3 puntos
if (yakuExterior(contenedorGrupos)) { if (yakuExterior(contenedorGrupos)) {
listaYakus.add(Yaku.Exterior) listaYakus.add(Yaku.Exterior)
} }
@ -80,11 +86,10 @@ fun obtenerListaYakus(contenedorGrupos: ContenedorGrupos, esManoAbierta: Boolean
var verificarTripleTriples = true var verificarTripleTriples = true
if (!esManoAbierta && yakuTripleTriples(contenedorGrupos)) { if (!esManoAbierta && yakuTripleTriples(contenedorGrupos)) {
listaYakus.add(Yaku.TripleTriplesCerrados) listaYakus.add(Yaku.TripleTriplesCerrados)
listaYakus.add(Yaku.TripleTriples)
verificarTripleTriples = false verificarTripleTriples = false
} }
// 4 puntos // 2 puntos
if (yakuSemiExterior(contenedorGrupos)) { if (yakuSemiExterior(contenedorGrupos)) {
listaYakus.add(Yaku.SemiExterior) listaYakus.add(Yaku.SemiExterior)
} }
@ -94,24 +99,18 @@ fun obtenerListaYakus(contenedorGrupos: ContenedorGrupos, esManoAbierta: Boolean
if (yakuNegro(contenedorGrupos)) { if (yakuNegro(contenedorGrupos)) {
listaYakus.add(Yaku.Negro) listaYakus.add(Yaku.Negro)
} }
if (yakuTripleCuadruples(contenedorGrupos)) {
listaYakus.add(Yaku.TripleCuadruples)
}
if (verificarEscalera && yakuEscalera(contenedorGrupos)) { if (verificarEscalera && yakuEscalera(contenedorGrupos)) {
listaYakus.add(Yaku.Escalera) listaYakus.add(Yaku.Escalera)
} }
// 3 puntos // 1 punto
if (yakuDobleSecuenciaPura(contenedorGrupos)) { if (yakuDobleSecuencia(contenedorGrupos)) {
listaYakus.add(Yaku.DobleSecuenciaPura) listaYakus.add(Yaku.DobleSecuencia)
} }
val cantidad = yakuRealeza(contenedorGrupos) val cantidad = yakuRealeza(contenedorGrupos)
if (cantidad > 0) { if (cantidad > 0) {
listaYakus.add(Yaku.Realeza) listaYakus.add(Yaku.Realeza)
} }
if (!esManoAbierta && yakuTripleSecuenciaCerrada(contenedorGrupos)) {
listaYakus.add(Yaku.TripleSecuenciaCerrada)
}
if (verificarTripleTriples && yakuTripleTriples(contenedorGrupos)) { if (verificarTripleTriples && yakuTripleTriples(contenedorGrupos)) {
listaYakus.add(Yaku.TripleTriples) listaYakus.add(Yaku.TripleTriples)
} }
@ -122,8 +121,8 @@ fun obtenerListaYakus(contenedorGrupos: ContenedorGrupos, esManoAbierta: Boolean
if (cantidadDragon > 0) { if (cantidadDragon > 0) {
listaYakus.add(Yaku.Dragones) listaYakus.add(Yaku.Dragones)
} }
if (yakuParUnico(contenedorGrupos)) { if (!esManoAbierta) {
listaYakus.add(Yaku.ParUnico) listaYakus.add(Yaku.ManoCerrada)
} }
return listaYakus return listaYakus

56
src/juego/yaku/yaku1.kt Normal file
View File

@ -0,0 +1,56 @@
package dev.araozu.juego.yaku
import dev.araozu.juego.CartaNumero
import dev.araozu.juego.ContenedorGrupos
// TODO
internal fun yakuDobleSecuencia(contenedorGrupos: ContenedorGrupos): Boolean {
return false
}
internal fun yakuRealeza(contenedorGrupos: ContenedorGrupos): Int {
var cantidadRealeza = 0
for (carrl in contenedorGrupos.tris) {
val cartaTri = carrl[0]
if (cartaTri.esRey()) cantidadRealeza++
}
return cantidadRealeza
}
internal fun yakuTripleTriples(contenedorGrupos: ContenedorGrupos) =
contenedorGrupos.tris.size == 3
internal fun yakuInterior(contenedorGrupos: ContenedorGrupos): Boolean {
for (carrl in contenedorGrupos.seqs) {
for (c in carrl) {
if (c !is CartaNumero) return false
if (c.esExterior()) return false
}
}
for (carrl in contenedorGrupos.tris) {
for (c in carrl) {
if (c !is CartaNumero) return false
if (c.esExterior()) return false
}
}
for (carrl in contenedorGrupos.pares) {
for (c in carrl) {
if (c !is CartaNumero) return false
if (c.esExterior()) return false
}
}
return true
}
// TODO
internal fun yakuDragones(contenedorGrupos: ContenedorGrupos): Int {
return 0
}

View File

@ -1,36 +1,42 @@
package dev.araozu.juego.yaku package dev.araozu.juego.yaku
import dev.araozu.juego.CartaRealeza import dev.araozu.juego.CartaDragon
import dev.araozu.juego.ContenedorGrupos import dev.araozu.juego.ContenedorGrupos
internal fun yakuRealezaDragones(contenedorGrupos: ContenedorGrupos): Boolean { internal fun yakuDragonesFull(contenedorGrupos: ContenedorGrupos): Boolean {
if (contenedorGrupos.tris.size != 3) return false if (contenedorGrupos.tris.size != 3) return false
for (carrl in contenedorGrupos.tris) { for (carrl in contenedorGrupos.tris) {
for (c in carrl) { for (c in carrl) {
if (!c.esDragonORey()) return false if (c !is CartaDragon) return false
} }
} }
for (carrl in contenedorGrupos.pares) { for (carrl in contenedorGrupos.pares) {
for (c in carrl) { for (c in carrl) {
if (!c.esDragonORey()) return false if (c !is CartaDragon) return false
} }
} }
return true return true
} }
internal fun yakuRealezaFull(contenedorGrupos: ContenedorGrupos): Boolean { internal fun yakuVerde(contenedorGrupos: ContenedorGrupos): Boolean {
if (contenedorGrupos.tris.size != 3) return false if (contenedorGrupos.tris.size != 3) return false
for (carrl in contenedorGrupos.tris) { for (carrl in contenedorGrupos.tris) {
for (c in carrl) { for (c in carrl) {
if (c !is CartaRealeza) return false if (!c.esCartaVerde()) return false
} }
} }
return false for (carrl in contenedorGrupos.pares) {
for (c in carrl) {
if (!c.esCartaVerde()) return false
}
}
return true
} }

View File

@ -1,42 +0,0 @@
package dev.araozu.juego.yaku
import dev.araozu.juego.CartaDragon
import dev.araozu.juego.ContenedorGrupos
internal fun yakuDragonesFull(contenedorGrupos: ContenedorGrupos): Boolean {
if (contenedorGrupos.tris.size != 3) return false
for (carrl in contenedorGrupos.tris) {
for (c in carrl) {
if (c !is CartaDragon) return false
}
}
for (carrl in contenedorGrupos.pares) {
for (c in carrl) {
if (c !is CartaDragon) return false
}
}
return true
}
internal fun yakuVerde(contenedorGrupos: ContenedorGrupos): Boolean {
if (contenedorGrupos.tris.size != 3) return false
for (carrl in contenedorGrupos.tris) {
for (c in carrl) {
if (!c.esCartaVerde()) return false
}
}
for (carrl in contenedorGrupos.pares) {
for (c in carrl) {
if (!c.esCartaVerde()) return false
}
}
return true
}

View File

@ -3,6 +3,11 @@ package dev.araozu.juego.yaku
import dev.araozu.juego.CartaNumero import dev.araozu.juego.CartaNumero
import dev.araozu.juego.ContenedorGrupos import dev.araozu.juego.ContenedorGrupos
internal fun yakuDobleSecuenciaPura(contenedorGrupos: ContenedorGrupos): Boolean {
return false
}
internal fun yakuSemiExterior(contenedorGrupos: ContenedorGrupos): Boolean { internal fun yakuSemiExterior(contenedorGrupos: ContenedorGrupos): Boolean {
for (carrl in contenedorGrupos.seqs) { for (carrl in contenedorGrupos.seqs) {
@ -84,17 +89,6 @@ internal fun yakuNegro(contenedorGrupos: ContenedorGrupos): Boolean {
return true return true
} }
internal fun yakuTripleCuadruples(contenedorGrupos: ContenedorGrupos): Boolean {
if (contenedorGrupos.tris.size != 3) return false
for (triple in contenedorGrupos.tris) {
if (triple.size != 4) return false
}
return true
}
// TODO: Las secuencias pueden no estar en orden // TODO: Las secuencias pueden no estar en orden
internal fun yakuEscalera(contenedorGrupos: ContenedorGrupos): Boolean { internal fun yakuEscalera(contenedorGrupos: ContenedorGrupos): Boolean {

View File

@ -3,66 +3,24 @@ package dev.araozu.juego.yaku
import dev.araozu.juego.CartaNumero import dev.araozu.juego.CartaNumero
import dev.araozu.juego.ContenedorGrupos import dev.araozu.juego.ContenedorGrupos
// TODO internal fun yakuExterior(contenedorGrupos: ContenedorGrupos): Boolean {
internal fun yakuDobleSecuenciaPura(contenedorGrupos: ContenedorGrupos): Boolean {
if (contenedorGrupos.tris.size != 3) return false
for (carrl in contenedorGrupos.tris) {
for (c in carrl) {
if (!c.esDragonORey() || c !is CartaNumero || !c.esExterior())
return false return false
} }
internal fun yakuRealeza(contenedorGrupos: ContenedorGrupos): Int {
var cantidadRealeza = 0
for (carrl in contenedorGrupos.tris) {
val cartaTri = carrl[0]
if (cartaTri.esRey()) cantidadRealeza++
}
return cantidadRealeza
}
internal fun yakuTripleSecuenciaCerrada(contenedorGrupos: ContenedorGrupos) =
contenedorGrupos.tris.size == 3
internal fun yakuTripleTriples(contenedorGrupos: ContenedorGrupos) =
contenedorGrupos.tris.size == 3
internal fun yakuInterior(contenedorGrupos: ContenedorGrupos): Boolean {
for (carrl in contenedorGrupos.seqs) {
for (c in carrl) {
if (c !is CartaNumero) return false
if (c.esExterior()) return false
}
}
for (carrl in contenedorGrupos.tris) {
for (c in carrl) {
if (c !is CartaNumero) return false
if (c.esExterior()) return false
}
} }
for (carrl in contenedorGrupos.pares) { for (carrl in contenedorGrupos.pares) {
for (c in carrl) { for (c in carrl) {
if (c !is CartaNumero) return false if (!c.esDragonORey() || c !is CartaNumero || !c.esExterior())
if (c.esExterior()) return false return false
} }
} }
return true return true
} }
// TODO
internal fun yakuDragones(contenedorGrupos: ContenedorGrupos): Int {
return 0
}
internal fun yakuParUnico(contenedorGrupos: ContenedorGrupos): Boolean {
val par = contenedorGrupos.pares[0]
val c1 = par[0]
val c2 = par[1]
if (c1 !is CartaNumero || c2 !is CartaNumero) return false
return c1.valor == c2.valor
}

View File

@ -3,26 +3,6 @@ package dev.araozu.juego.yaku
import dev.araozu.juego.CartaNumero import dev.araozu.juego.CartaNumero
import dev.araozu.juego.ContenedorGrupos import dev.araozu.juego.ContenedorGrupos
internal fun yakuExterior(contenedorGrupos: ContenedorGrupos): Boolean {
if (contenedorGrupos.tris.size != 3) return false
for (carrl in contenedorGrupos.tris) {
for (c in carrl) {
if (!c.esDragonORey() || c !is CartaNumero || !c.esExterior())
return false
}
}
for (carrl in contenedorGrupos.pares) {
for (c in carrl) {
if (!c.esDragonORey() || c !is CartaNumero || !c.esExterior())
return false
}
}
return true
}
// TODO: Las secuencias pueden no estar en orden // TODO: Las secuencias pueden no estar en orden
internal fun yakuEscaleraFull(contenedorGrupos: ContenedorGrupos): Boolean { internal fun yakuEscaleraFull(contenedorGrupos: ContenedorGrupos): Boolean {
@ -57,4 +37,3 @@ internal fun yakuEscaleraFull(contenedorGrupos: ContenedorGrupos): Boolean {
return true return true
} }

46
src/juego/yaku/yaku7.kt Normal file
View File

@ -0,0 +1,46 @@
package dev.araozu.juego.yaku
import dev.araozu.juego.CartaRealeza
import dev.araozu.juego.ContenedorGrupos
internal fun yakuA10(contenedorGrupos: ContenedorGrupos): Boolean {
return false
}
internal fun yakuEscaleraPerfecta(contenedorGrupos: ContenedorGrupos): Boolean {
return false
}
internal fun yakuRealezaDragones(contenedorGrupos: ContenedorGrupos): Boolean {
if (contenedorGrupos.tris.size != 3) return false
for (carrl in contenedorGrupos.tris) {
for (c in carrl) {
if (!c.esDragonORey()) return false
}
}
for (carrl in contenedorGrupos.pares) {
for (c in carrl) {
if (!c.esDragonORey()) return false
}
}
return true
}
internal fun yakuRealezaFull(contenedorGrupos: ContenedorGrupos): Boolean {
if (contenedorGrupos.tris.size != 3) return false
for (carrl in contenedorGrupos.tris) {
for (c in carrl) {
if (c !is CartaRealeza) return false
}
}
return true
}

46
src/tests/Yaku10Test.kt Normal file
View File

@ -0,0 +1,46 @@
package dev.araozu.tests
import dev.araozu.juego.*
import dev.araozu.juego.yaku.Yaku
fun testYakuVerde(): Boolean {
val cartasMano = carr(
CartaDragonVerde(),
CartaDragonVerde(),
CartaRealezaJ(),
CartaRealezaJ(),
CartaRealezaK(),
CartaRealezaK(),
CartaRealezaK(),
CartaRealezaQ(),
CartaRealezaQ(),
CartaRealezaQ()
)
val op = OportunidadRon.verificar(
valorCarta = c(CartaDragonVerde()),
cartasMano = cartasMano
)
return existeYaku(op, Yaku.Verde)
}
fun testYakuDragonesFull(): Boolean {
val cartas = carr(
CartaDragonVerde(),
CartaDragonAzul(),
CartaDragonAzul(),
CartaDragonAzul(),
CartaDragonRojo(),
CartaDragonRojo(),
CartaDragonRojo(),
CartaDragonNegro(),
CartaDragonNegro(),
CartaDragonNegro()
)
val op = OportunidadRon.verificar(
valorCarta = c(CartaDragonVerde()),
cartasMano = cartas
)
return existeYaku(op, Yaku.DragonesFull)
}

60
src/tests/Yaku1Test.kt Normal file
View File

@ -0,0 +1,60 @@
package dev.araozu.tests
import dev.araozu.juego.*
import dev.araozu.juego.yaku.Yaku
fun testYakuDobleSecuencia(): Boolean {
val cartas = arrayListOf(
10, 11, 12, 12, 14, 15, 52, 52, 192, 192
)
val op = OportunidadRon.verificar(
valorCarta = 52,
cartasMano = cartas
)
return existeYaku(op, Yaku.DobleSecuencia)
}
fun testYakuRealeza(): Boolean {
val cartas = arrayListOf(
6, 8, 10, 40, 42, 44, 96, 96, 256, 256
)
val op = OportunidadRon.verificar(
valorCarta = 256,
cartasMano = cartas
)
return existeYaku(op, Yaku.Realeza)
}
fun testYakuTripleTriples(): Boolean {
val cartas = arrayListOf(
2,
2,
3,
20,
20,
96,
96
)
val op = OportunidadRon.verificar(
valorCarta = 96,
cartasMano = cartas,
gruposAbiertos = arrayListOf(
arrayListOf(34, 34, 35)
)
)
return existeYaku(op, Yaku.TripleTriples)
}
fun testYakuInterior(): Boolean {
val cartas = arrayListOf(
4, 6, 8, 6, 8, 10, 48
)
val op = OportunidadRon.verificar(
valorCarta = 48,
cartasMano = cartas,
gruposAbiertos = arrayListOf(
arrayListOf(44, 44, 45)
)
)
return existeYaku(op, Yaku.Interior)
}

86
src/tests/Yaku2Test.kt Normal file
View File

@ -0,0 +1,86 @@
package dev.araozu.tests
import dev.araozu.juego.*
import dev.araozu.juego.yaku.Yaku
fun testYakuDobleSecuenciaPura(): Boolean {
val cartas = arrayListOf(
2,
2,
4,
4,
6,
6,
34,
34,
35,
96
)
val op = OportunidadRon.verificar(
valorCarta = 96,
cartasMano = cartas
)
return existeYaku(op, Yaku.DobleSecuenciaPura)
}
fun testYakuSemiExterior(): Boolean {
val cartas = arrayListOf(
2,
4,
6,
20,
20,
34,
36,
38,
96,
96
)
val op = OportunidadRon.verificar(
valorCarta = 96,
cartasMano = cartas
)
return existeYaku(op, Yaku.SemiExterior)
}
fun testYakuRojo(): Boolean {
val cartas = arrayListOf(
38,
38,
38,
52,
52,
34,
34,
35,
c(CartaDragonRojo()),
c(CartaDragonRojo())
)
val op = OportunidadRon.verificar(
valorCarta = c(CartaDragonRojo()),
cartasMano = cartas
)
return existeYaku(op, Yaku.Rojo)
}
fun testYakuNegro(): Boolean {
val cartas = arrayListOf(
2, 2, 2, 10, 10, 10, 16, 16, 20, 20
)
val op = OportunidadRon.verificar(
valorCarta = 20,
cartasMano = cartas
)
return existeYaku(op, Yaku.Negro)
}
fun testYakuEscalera(): Boolean {
val cartas = arrayListOf(
2, 4, 6, 8, 10, 12, 14, 16, 18, 96
)
val op = OportunidadRon.verificar(
valorCarta = 96,
cartasMano = cartas
)
return existeYaku(op, Yaku.Escalera)
}

44
src/tests/Yaku3Test.kt Normal file
View File

@ -0,0 +1,44 @@
package dev.araozu.tests
import dev.araozu.juego.*
import dev.araozu.juego.yaku.Yaku
fun testYakuExterior(): Boolean {
val cartas = arrayListOf(
2,
2,
3,
20,
20,
34,
34,
35,
96,
96
)
val op = OportunidadRon.verificar(
valorCarta = 96,
cartasMano = cartas
)
return existeYaku(op, Yaku.Exterior)
}
fun testYakuTripleTriplesCerrados(): Boolean {
val cartas = arrayListOf(
2,
2,
3,
20,
20,
34,
34,
35,
96,
96
)
val op = OportunidadRon.verificar(
valorCarta = 96,
cartasMano = cartas
)
return existeYaku(op, Yaku.TripleTriplesCerrados)
}

24
src/tests/Yaku5Test.kt Normal file
View File

@ -0,0 +1,24 @@
package dev.araozu.tests
import dev.araozu.juego.*
import dev.araozu.juego.yaku.Yaku
fun testYakuEscaleraFull(): Boolean {
val cartas = arrayListOf(
2,
3,
4,
6,
8,
10,
13,
14,
16,
18
)
val op = OportunidadRon.verificar(
valorCarta = 20,
cartasMano = cartas
)
return existeYaku(op, Yaku.EscaleraFull)
}

84
src/tests/Yaku7Test.kt Normal file
View File

@ -0,0 +1,84 @@
package dev.araozu.tests
import dev.araozu.juego.*
import dev.araozu.juego.yaku.Yaku
fun testYakuA10(): Boolean {
val cartasMano = arrayListOf(
2,
2,
3,
20,
20,
21,
34,
34,
52,
52
)
val op = OportunidadRon.verificar(
valorCarta = 35,
cartasMano = cartasMano
)
return existeYaku(op, Yaku.A10)
}
fun testYakuEscaleraPerfecta(): Boolean {
val cartas = arrayListOf(
2,
2,
4,
6,
8,
10,
12,
14,
16,
18
)
val op = OportunidadRon.verificar(
valorCarta = 20,
cartasMano = cartas
)
return existeYaku(op, Yaku.EscaleraPerfecta)
}
fun testYakuRealezaFull(): Boolean {
val cartas = arrayListOf(
2,
192,
192,
192,
224,
224,
224,
256,
256,
256
)
val op = OportunidadRon.verificar(
valorCarta = 2,
cartasMano = cartas
)
return existeYaku(op, Yaku.RealezaFull)
}
fun testYakuRealezaDragones(): Boolean {
val cartas = arrayListOf(
256,
64,
64,
64,
128,
128,
128,
192,
192,
192
)
val op = OportunidadRon.verificar(
valorCarta = 256,
cartasMano = cartas
)
return existeYaku(op, Yaku.RealezaDragones)
}

53
src/tests/YakuTest.kt Normal file
View File

@ -0,0 +1,53 @@
package dev.araozu.tests
import dev.araozu.juego.*
import dev.araozu.juego.yaku.Yaku
fun c(c: Carta): Int = c.valor
fun carr(vararg carr: Carta): ArrayList<Int> {
val cartas = arrayListOf<Int>()
cartas.addAll(carr.map(::c))
return cartas
}
fun existeYaku(op: OportunidadRon?, yaku: Yaku): Boolean {
if (op == null) return false
return null != op.yaku.find { it == yaku }
}
fun impErr(res: Boolean, nombreYaku: String) {
if (!res) System.err.println("Error al ejecutar yaku $nombreYaku")
}
fun main() {
// Yaku10
impErr(testYakuVerde(), "Verde")
impErr(testYakuDragonesFull(), "Dragones Full")
// Yaku7
impErr(testYakuA10(), "A-10")
impErr(testYakuEscaleraPerfecta(), "Escalera Perfecta")
impErr(testYakuRealezaFull(), "Realeza Full")
impErr(testYakuRealezaDragones(), "Realeza y Dragones")
// Yaku5
impErr(testYakuEscaleraFull(), "Escalera Full")
// Yaku3
impErr(testYakuExterior(), "Exterior")
impErr(testYakuTripleTriplesCerrados(), "Triple Triples Cerrados")
// Yaku2
impErr(testYakuDobleSecuenciaPura(), "Doble Secuencia Pura")
impErr(testYakuSemiExterior(), "Semi Exterior")
impErr(testYakuRojo(), "Rojo")
impErr(testYakuNegro(), "Negro")
impErr(testYakuEscalera(), "Escalera")
// Yaku1
impErr(testYakuDobleSecuencia(), "Doble Secuencia")
impErr(testYakuRealeza(), "Realeza")
impErr(testYakuTripleTriples(), "Triple Triples")
impErr(testYakuInterior(), "Interior")
}