Refactor the roll mechanism to allow broader instructions set.

This commit is contained in:
Thomas Andres Gomez 2024-11-27 14:09:26 +01:00
parent d2ae180cf7
commit 8d93d46cce
10 changed files with 207 additions and 146 deletions

View file

@ -21,13 +21,13 @@ class ArithmeticParser {
)
@Throws(Instruction.UnknownInstruction::class)
fun parse(value: String): List<Arithmetic> {
fun parse(value: String): List<Instruction> {
return operatorParser.findAll(value).mapNotNull {
val (operator, instruction) = it.destructured
if (instruction.isNotBlank()) {
Arithmetic(
parseInstruction(
sign = parseOperator(operator),
instruction = parseInstruction(instruction),
instruction = instruction,
)
} else {
null
@ -36,10 +36,14 @@ class ArithmeticParser {
}
@Throws(Instruction.UnknownInstruction::class)
fun parseInstruction(instruction: String): Instruction {
fun parseInstruction(
sign: Int,
instruction: String
): Instruction {
diceParser.find(instruction)?.let {
val (modifier, quantity, faces) = it.destructured
Instruction.Dice(
sign = sign,
modifier = parseModifier(value = modifier),
quantity = quantity.toInt(),
faces = faces.toInt(),
@ -47,11 +51,17 @@ class ArithmeticParser {
}?.let { return it }
wordParser.find(instruction)?.let {
parseWord(value = it.value)
parseWord(
sign = sign,
value = it.value
)
}?.let { return it }
flatParser.find(instruction)?.let {
Instruction.Flat(value = it.value.toInt())
Instruction.Flat(
sign = sign,
value = it.value.toInt(),
)
}?.let { return it }
throw Instruction.UnknownInstruction(payload = instruction)
@ -74,31 +84,39 @@ class ArithmeticParser {
}
}
private fun parseWord(value: String): Word? {
private fun parseWord(
sign: Int,
value: String,
): Word? {
return try {
Word.valueOf(value)
Word(
sign = sign,
type = Word.Type.valueOf(value),
)
} catch (_: Exception) {
return null
}
}
fun convertInstructionToString(
instructions: List<Arithmetic>,
instructions: List<Instruction>,
): String {
return instructions.map {
val sign = if (it.sign > 0) "+" else "-"
val value = when (val instruction = it.instruction) {
is Instruction.Dice -> "${instruction.modifier ?: ""}${instruction.quantity}d${instruction.faces}"
is Instruction.Flat -> "${instruction.value}"
Word.BDC -> Word.BDC.name
Word.BDD -> Word.BDD.name
Word.STR -> Word.STR.name
Word.DEX -> Word.DEX.name
Word.CON -> Word.CON.name
Word.HEI -> Word.HEI.name
Word.INT -> Word.INT.name
Word.POW -> Word.POW.name
Word.CHA -> Word.CHA.name
val value = when (it) {
is Instruction.Dice -> "${it.modifier ?: ""}${it.quantity}d${it.faces}"
is Instruction.Flat -> "${it.value}"
is Word -> when (it.type) {
Word.Type.BDC -> Word.Type.BDC.name
Word.Type.BDD -> Word.Type.BDD.name
Word.Type.STR -> Word.Type.STR.name
Word.Type.DEX -> Word.Type.DEX.name
Word.Type.CON -> Word.Type.CON.name
Word.Type.HEI -> Word.Type.HEI.name
Word.Type.INT -> Word.Type.INT.name
Word.Type.POW -> Word.Type.POW.name
Word.Type.CHA -> Word.Type.CHA.name
}
}
"$sign$value"
}.joinToString(separator = " ") {
@ -107,6 +125,6 @@ class ArithmeticParser {
}
companion object {
val words: List<String> = Word.entries.map { it.name }
val words: List<String> = Word.Type.entries.map { it.name }
}
}

View file

@ -1,40 +1,64 @@
package com.pixelized.desktop.lwa.parser.arithmetic
class Arithmetic(
sealed class Instruction(
val sign: Int,
val instruction: Instruction,
)
sealed interface Instruction {
data class Dice(
) {
class Dice(
sign: Int,
val modifier: Modifier?,
val quantity: Int,
val faces: Int,
) : Instruction {
) : Instruction(
sign = sign,
) {
enum class Modifier {
ADVANTAGE,
DISADVANTAGE,
EMPHASIS,
}
override fun toString(): String {
return "${sign.sign}${quantity}d${faces}"
}
}
data class Flat(
class Flat(
sign: Int,
val value: Int,
) : Instruction
) : Instruction(
sign = sign,
) {
override fun toString(): String {
return "${sign.sign}${value}"
}
}
enum class Word : Instruction {
BDC, // Damages bonus for melee
BDD, // Damages bonus for range
STR, // Strength
DEX, // Dexterity
CON, // Constitution
HEI, // Height
INT, // Intelligence
POW, // Power
CHA, // Charisma
class Word(
sign: Int,
val type: Type,
) : Instruction(
sign = sign
) {
enum class Type {
BDC, // Damages bonus for melee
BDD, // Damages bonus for range
STR, // Strength
DEX, // Dexterity
CON, // Constitution
HEI, // Height
INT, // Intelligence
POW, // Power
CHA, // Charisma
}
override fun toString(): String {
return "${sign.sign}${type}"
}
}
class UnknownInstruction(payload: String) : RuntimeException(
"Unknown instruction exception. Unable to parse the following payload:\"$payload\" into an instruction"
)
val Int.sign: String get() = if (this > 0) "+" else "-"
}