diff --git a/src/main/kotlin/gay/j10a1n15/sillygames/commands/CommandManager.kt b/src/main/kotlin/gay/j10a1n15/sillygames/commands/CommandManager.kt index 1afa792..6395d4c 100644 --- a/src/main/kotlin/gay/j10a1n15/sillygames/commands/CommandManager.kt +++ b/src/main/kotlin/gay/j10a1n15/sillygames/commands/CommandManager.kt @@ -1,7 +1,7 @@ package gay.j10a1n15.sillygames.commands -import gay.j10a1n15.sillygames.games.Snake +import gay.j10a1n15.sillygames.games.wordle.Wordle import gay.j10a1n15.sillygames.screens.FullScreen import gay.j10a1n15.sillygames.screens.PictureInPicture import gay.j10a1n15.sillygames.utils.SillyUtils.display @@ -13,7 +13,7 @@ class CommandManager { init { registerCommand("fullscreen") { - FullScreen(Snake()).display() + FullScreen(Wordle()).display() } registerCommand("pip") { PictureInPicture.visible = !PictureInPicture.visible diff --git a/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/Wordle.kt b/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/Wordle.kt index 5d23c51..546b2be 100644 --- a/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/Wordle.kt +++ b/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/Wordle.kt @@ -6,6 +6,7 @@ import gg.essential.elementa.components.UIBlock import gg.essential.elementa.components.UIContainer import gg.essential.elementa.components.UIRoundedRectangle import gg.essential.elementa.components.UIText +import gg.essential.elementa.components.input.UITextInput import gg.essential.elementa.constraints.CenterConstraint import gg.essential.elementa.constraints.ChildBasedMaxSizeConstraint import gg.essential.elementa.constraints.ChildBasedSizeConstraint @@ -14,11 +15,14 @@ import gg.essential.elementa.constraints.SiblingConstraint import gg.essential.elementa.dsl.childOf import gg.essential.elementa.dsl.constrain import gg.essential.elementa.dsl.effect +import gg.essential.elementa.dsl.percent import gg.essential.elementa.dsl.pixels +import gg.essential.elementa.dsl.plus import gg.essential.elementa.dsl.toConstraint import gg.essential.elementa.effects.OutlineEffect import gg.essential.elementa.utils.withAlpha import gg.essential.universal.UKeyboard +import java.awt.Color private const val BOX_SIZE = 30 private const val BOX_SPACING = 5 @@ -36,6 +40,43 @@ class Wordle : Game() { private var text: String = "" private var time: Long = 0 + private val wordIndexInput = UITextInput("Custom Word Index").constrain { + width = 90.percent + height = 10.pixels() + x = CenterConstraint() + y = CenterConstraint() + color = Color.GRAY.toConstraint() + }.onKeyType { _, key -> + if (key == UKeyboard.KEY_ENTER) { + val index = (this as UITextInput).getText().toIntOrNull() + if (index != null) { + state.reset(index) + setText("") + } + } + }.onMouseEnter { + grabWindowFocus() + }.onMouseLeave { + releaseWindowFocus() + } as UITextInput + + private fun getWordIndexInputDisplay(): UIComponent? { + if (state.tries != 0) return null + else { + val container = UIBlock().constrain { + this.width = 20.percent() + this.height = 10.percent() + this.x = CenterConstraint() + this.y = 100.percent() + this.color = WordlePalette.GRAY.toConstraint() + } + + wordIndexInput childOf container + + return container + } + } + private fun getWordDisplay(): UIComponent { return UIContainer().apply { this.constrain { @@ -188,18 +229,23 @@ class Wordle : Game() { val timeDiff = System.currentTimeMillis() - time - UIText(text, true).constrain { - this.x = CenterConstraint() - this.y = SiblingConstraint(20f, true) - this.color = WordlePalette.WHITE.withAlpha( - // face in and out over first 1.5 seconds and last 1.5 seconds - when (timeDiff) { - in 0..1500 -> (timeDiff / 1500f).coerceIn(0f, 1f) - in 3500..Int.MAX_VALUE -> ((5000 - timeDiff) / 1500f).coerceIn(0f, 1f) - else -> 1f - } - ).toConstraint() - } childOf this + val multiLineText = text.split("\n").reversed() + for ((i, line) in multiLineText.withIndex()) { + UIText(line, true).constrain { + this.x = CenterConstraint() + this.y = SiblingConstraint(20f, true) + (20f * i).pixels() + this.color = WordlePalette.WHITE.withAlpha( + // face in and out over first 1.5 seconds and last 1.5 seconds + when (timeDiff) { + in 0..1500 -> (timeDiff / 1500f).coerceIn(0f, 1f) + in 3500..Int.MAX_VALUE -> ((5000 - timeDiff) / 1500f).coerceIn(0f, 1f) + else -> 1f + }, + ).toConstraint() + } childOf this + } + + getWordIndexInputDisplay()?.childOf(this) } } @@ -209,6 +255,7 @@ class Wordle : Game() { } override fun onKeyPressed(key: Int) { + if (wordIndexInput.hasFocus()) return when (key) { UKeyboard.KEY_ENTER -> guess() else -> state.keyPress(key) diff --git a/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/WordleState.kt b/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/WordleState.kt index fb78ffa..dc8879c 100644 --- a/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/WordleState.kt +++ b/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/WordleState.kt @@ -6,25 +6,27 @@ import gg.essential.elementa.utils.invisible import gg.essential.universal.UKeyboard import java.awt.Color -class WordleState { +class WordleState(private val wordIndexInput: Int? = null) { private val letterKeys = setOf( UKeyboard.KEY_A, UKeyboard.KEY_B, UKeyboard.KEY_C, UKeyboard.KEY_D, UKeyboard.KEY_E, UKeyboard.KEY_F, UKeyboard.KEY_G, UKeyboard.KEY_H, UKeyboard.KEY_I, UKeyboard.KEY_J, UKeyboard.KEY_K, UKeyboard.KEY_L, UKeyboard.KEY_M, UKeyboard.KEY_N, UKeyboard.KEY_O, UKeyboard.KEY_P, UKeyboard.KEY_Q, UKeyboard.KEY_R, UKeyboard.KEY_S, UKeyboard.KEY_T, UKeyboard.KEY_U, UKeyboard.KEY_V, UKeyboard.KEY_W, UKeyboard.KEY_X, - UKeyboard.KEY_Y, UKeyboard.KEY_Z + UKeyboard.KEY_Y, UKeyboard.KEY_Z, ) - var word = WordleWordList.getWord() + var word = wordIndexInput?.let { WordleWordList.getWord(it) } ?: WordleWordList.getWord() + var wordIndex = wordIndexInput ?: WordleWordList.getIndex(word) val guesses = Array(6) { "" } val colors = Array(6) { Array(5) { Color.WHITE.invisible() } } val letters = mutableMapOf() var tries = 0 var reset = false - fun reset() { - word = WordleWordList.getWord() + fun reset(wordIndex: Int? = null) { + word = wordIndex?.let { WordleWordList.getWord(it) } ?: WordleWordList.getWord() + this.wordIndex = wordIndex ?: WordleWordList.getIndex(word) guesses.fill("") colors.forEach { it.fill(Color.WHITE.invisible()) } letters.clear() @@ -44,9 +46,11 @@ class WordleState { key == UKeyboard.KEY_BACKSPACE -> { guesses[tries] = guesses[tries].dropLast(1) } + key in letterKeys && guesses[tries].length < 5 -> { enterChar(key.getKeyCodeName()?.lowercase()?.first() ?: return) } + key == UKeyboard.KEY_BACKSLASH -> { println("The word is $word") } @@ -90,10 +94,10 @@ class WordleState { tries++ if (guess.lowercase() == word) { reset = true - return "You won!" + return "You won!\nWord Index: $wordIndex" } else if (tries >= 6) { reset = true - return "You lost! The word was '$word'" + return "You lost! The word was '$word'\nWord Index: $wordIndex" } return null } diff --git a/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/WordleWordList.kt b/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/WordleWordList.kt index 852b394..7ada523 100644 --- a/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/WordleWordList.kt +++ b/src/main/kotlin/gay/j10a1n15/sillygames/games/wordle/WordleWordList.kt @@ -13,9 +13,16 @@ object WordleWordList { val allowedStream = this::class.java.getResourceAsStream("/wordle/allowed.txt") this.allowed.addAll(IOUtils.readLines(allowedStream, Charsets.UTF_8)) this.allowed.addAll(this.words) + + val seed = 69420L + this.words.shuffle(java.util.Random(seed)) } fun isAllowed(word: String) = this.allowed.contains(word.lowercase()) fun getWord() = this.words.random() + + fun getWord(index: Int) = this.words.getOrNull(index) ?: this.words.random() + + fun getIndex(word: String) = this.words.indexOf(word) }