Add support for Hp grow bonus and Leaning bonus.

This commit is contained in:
Thomas Andres Gomez 2024-11-30 18:05:55 +01:00
parent 3419afbe59
commit ca20078ffa
18 changed files with 526 additions and 402 deletions

View file

@ -42,6 +42,8 @@
<string name="character_sheet_edit__sub_characteristics__power_point">Points de pouvoir</string>
<string name="character_sheet_edit__sub_characteristics__damage_bonus">Bonus aux dégats</string>
<string name="character_sheet_edit__sub_characteristics__armor">Armure</string>
<string name="character_sheet_edit__sub_characteristics__learning">Bonus d'apprentissage</string>
<string name="character_sheet_edit__sub_characteristics__hp_grow">Bonus de PV</string>
<string name="character_sheet_edit__skills__common_title">Compétences communes</string>
<string name="character_sheet_edit__skills__special_title">Compétences spéciales</string>
<string name="character_sheet_edit__skills__special_action">Ajouter une compétence spéciale</string>
@ -94,6 +96,8 @@
<string name="character_sheet__sub_characteristics__power_point">Points de pouvoir</string>
<string name="character_sheet__sub_characteristics__damage_bonus">Bonus aux dégats</string>
<string name="character_sheet__sub_characteristics__armor">Armure</string>
<string name="character_sheet__sub_characteristics__learning">Bonus d'apprentissage</string>
<string name="character_sheet__sub_characteristics__hp_grow">Bonus de PV</string>
<string name="character_sheet__skills__common_title">Compétences communes</string>
<string name="character_sheet__skills__special_title">Compétences spéciales</string>
<string name="character_sheet__skills__magic_title">Compétences magiques</string>
@ -113,7 +117,8 @@
<string name="tooltip__sub_characteristics__power_point">les points de pouvoir sont égaux au POU et sont dépensés pour utiliser la magie ou dautres pouvoirs. Tous les points de pouvoir régénèrent naturellement après une nuit de repos.</string>
<string name="tooltip__sub_characteristics__bonus_damage">Les personnages plus massifs ou plus forts infligent plus de dégâts quand ils frappent leurs ennemis en combat au corps à corps. Le modificateur sapplique aux dégâts infligés par toute attaque portée par les personnages avec des armes de mêlée (BDC). La moitié de ce bonus s'applique aux attaques de lancer (BDD).</string>
<string name="tooltip__sub_characteristics__armor">Une armure protège son porteur des blessures. Lorsquun personnage est touché en combat par une attaque non magique, soustrayez les points darmure aux points de dégâts infligés. Les dommages au-delà de la protection de larmure surpassent celle-ci et sont infligés au personnage, réduisant ses points de vie actuels.</string>
<string name="tooltip__sub_characteristics__learning">Plus un personnage est intelligent, plus il assimile rapidement les connaissances et plus il digère son expérience efficacement. Ce modificateur s'applique au score des compétences nouvellement acquises et aux jets d'expériences. Il est égal à (INT - 10) x 2 avec une valeur minimale de zéro.</string>
<string name="tooltip__sub_characteristics__hp_grow">Plus un personnage est de bonne constitution, plus son corps se renforce rapidement. Ce modificateur indique le nombre de "PV" maximum que le personnage gagne à chaque progression. Il est égal à CON / 3, arrondi à l'inférieur.</string>
<string name="tooltip__skills__combat">Attaque en combat à mains nues. Une attaque réussie inflige 1D3 + BDGT.</string>
<string name="tooltip__skills__dodge">Éviter une attaque, un projectile, etc.</string>
<string name="tooltip__skills__grab">Maitriser/immobiliser un adversaire.</string>

View file

@ -1,8 +1,7 @@
package com.pixelized.desktop.lwa
import com.pixelized.desktop.lwa.business.DamageBonusUseCase
import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
import com.pixelized.desktop.lwa.business.RollUseCase
import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase
import com.pixelized.desktop.lwa.business.SkillStepUseCase
import com.pixelized.desktop.lwa.business.SkillValueComputationUseCase
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
@ -71,9 +70,8 @@ val parserDependencies
val useCaseDependencies
get() = module {
factoryOf(::DamageBonusUseCase)
factoryOf(::SkillStepUseCase)
factoryOf(::SkillNormalizerUseCase)
factoryOf(::RollUseCase)
factoryOf(::SkillValueComputationUseCase)
factoryOf(::CharacterSheetUseCase)
}

View file

@ -0,0 +1,56 @@
package com.pixelized.desktop.lwa.business
import kotlin.math.ceil
import kotlin.math.max
class CharacterSheetUseCase {
fun normalize(value: Int): Int {
return value - value % 5 // (truncate(value.toFloat() / 5f) * 5f).toInt()
}
fun defaultMovement(): Int = 10
fun defaultMaxHp(
constitution: Int,
height: Int,
): Int {
return (ceil((constitution + height) / 2f).toInt())
}
fun defaultMaxPower(
power: Int,
): Int {
return power
}
fun defaultDamageBonus(
strength: Int,
height: Int,
): String {
return defaultDamageBonus(sum = strength + height)
}
fun defaultDamageBonus(
sum: Int,
): String {
return when {
sum < 12 -> "-1d6"
sum in 12..17 -> "-1d4"
sum in 18..22 -> "+0"
sum in 23..29 -> "+1d4"
sum in 30..39 -> "+1d6"
else -> "+2d6"
}
}
fun defaultArmor(): Int = 0
fun defaultLearning(intelligence: Int): Int {
return max(0, (intelligence - 10) * 2)
}
fun defaultHpGrow(constitution: Int): Int {
return (constitution / 3)
}
}

View file

@ -1,19 +0,0 @@
package com.pixelized.desktop.lwa.business
class DamageBonusUseCase {
fun bonusDamage(strength: Int, height: Int): String {
return bonusDamage(stat = strength + height)
}
fun bonusDamage(stat: Int): String {
return when {
stat < 12 -> "-1d6"
stat in 12..17 -> "-1d4"
stat in 18..22 -> "+0"
stat in 23..29 -> "+1d4"
stat in 30..39 -> "+1d6"
else -> "+2d6"
}
}
}

View file

@ -7,10 +7,6 @@ import kotlin.math.min
class RollUseCase {
fun rollD100(): Int {
return roll(modifier = null, quantity = 1, faces = 100)
}
fun roll(dice: Instruction.Dice): Int {
return roll(
modifier = dice.modifier,
@ -19,9 +15,13 @@ class RollUseCase {
)
}
fun roll(modifier: Instruction.Dice.Modifier?, quantity: Int, faces: Int): Int {
fun roll(
modifier: Instruction.Dice.Modifier? = null,
quantity: Int = 1,
faces: Int,
): Int {
print("{")
return sum(count = quantity) {
return sum(count = quantity) { left ->
when (modifier) {
Instruction.Dice.Modifier.ADVANTAGE -> {
val roll1 = roll(faces = faces)
@ -54,6 +54,8 @@ class RollUseCase {
null -> {
roll(faces = faces).also { print("$it") }
}
}.also {
if (quantity > 1 && left != 1) print(",")
}
}.also {
print("}:")
@ -61,14 +63,14 @@ class RollUseCase {
}
private fun roll(faces: Int): Int {
return (Math.random() * faces.toDouble() + 1).toInt()
return (Math.random() * faces.toDouble() + 1.0).toInt()
}
private fun sum(count: Int, block: () -> Int): Int {
private fun sum(count: Int, block: (Int) -> Int): Int {
return if (count > 1) {
block() + sum(count - 1, block)
block(count) + sum(count - 1, block)
} else {
block()
block(count)
}
}
}

View file

@ -1,9 +0,0 @@
package com.pixelized.desktop.lwa.business
import kotlin.math.truncate
class SkillNormalizerUseCase {
fun normalize(value: Int): Int {
return (truncate(value.toFloat() / 5f) * 5f).toInt()
}
}

View file

@ -1,16 +1,15 @@
package com.pixelized.desktop.lwa.parser.arithmetic
sealed class Instruction(
val sign: Int,
) {
class Dice(
sign: Int,
sealed class Instruction {
abstract val sign: Int
data class Dice(
override val sign: Int,
val modifier: Modifier?,
val quantity: Int,
val faces: Int,
) : Instruction(
sign = sign,
) {
) : Instruction() {
enum class Modifier {
ADVANTAGE,
DISADVANTAGE,
@ -29,23 +28,20 @@ sealed class Instruction(
}
}
class Flat(
sign: Int,
data class Flat(
override val sign: Int,
val value: Int,
) : Instruction(
sign = sign,
) {
) : Instruction() {
override fun toString(): String {
return "${sign.sign}${value}"
}
}
class Word(
sign: Int,
data class Word(
override val sign: Int,
val type: Type,
) : Instruction(
sign = sign
) {
) : Instruction() {
enum class Type {
BDC, // Damages bonus for melee
BDD, // Damages bonus for range

View file

@ -1,34 +1,13 @@
package com.pixelized.desktop.lwa.repository.characterSheet
import com.pixelized.desktop.lwa.business.DamageBonusUseCase
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJson
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJsonV1
import kotlinx.coroutines.runBlocking
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__acrobatics
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__aid
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__athletics
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__bargain
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__combat
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__discretion
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__dodge
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__empathy
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__grab
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__intimidation
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__perception
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__persuasion
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__search
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__sleight_of_hand
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__spiel
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__throw
import org.jetbrains.compose.resources.getString
import kotlin.math.ceil
class CharacterSheetJsonFactory(
private val bonusDamageUseCase: DamageBonusUseCase,
private val skillDescriptionFactory: SkillDescriptionFactory,
private val characterSheetUseCase: CharacterSheetUseCase,
) {
fun convertToJson(
@ -51,6 +30,8 @@ class CharacterSheetJsonFactory(
maxPP = if (sheet.overrideMaxPP) sheet.maxPp else null,
damageBonus = if (sheet.overrideDamageBonus) sheet.damageBonus else null,
armor = if (sheet.overrideArmor) sheet.armor else null,
learning = if (sheet.overrideLearning) sheet.learning else null,
hpGrowf = if (sheet.overrideHpGrow) sheet.hpGrow else null,
skills = sheet.commonSkills.map {
CharacterSheetJsonV1.Skill(
id = it.id,
@ -108,8 +89,8 @@ class CharacterSheetJsonFactory(
private suspend fun convertFromV1(
json: CharacterSheetJsonV1,
): CharacterSheet {
val sheet = CharacterSheet(
): CharacterSheet = characterSheetUseCase.run {
CharacterSheet(
id = json.id,
name = json.name,
strength = json.strength,
@ -120,21 +101,27 @@ class CharacterSheetJsonFactory(
power = json.power,
charisma = json.charisma,
overrideMovement = json.movement != null,
movement = json.movement ?: 10,
movement = json.movement ?: defaultMovement(),
currentHp = json.currentHp,
overrideMaxHp = json.maxHp != null,
maxHp = json.maxHp ?: (ceil((json.constitution + json.height) / 2f).toInt()),
maxHp = json.maxHp ?: defaultMaxHp(
constitution = json.constitution,
height = json.height,
),
currentPp = json.currentPP,
overrideMaxPP = json.maxPP != null,
maxPp = json.maxPP ?: json.power,
maxPp = json.maxPP ?: defaultMaxPower(power = json.power),
overrideDamageBonus = json.damageBonus != null,
damageBonus = json.damageBonus
?: bonusDamageUseCase.bonusDamage(
strength = json.strength,
height = json.height
),
damageBonus = json.damageBonus ?: defaultDamageBonus(
strength = json.strength,
height = json.height,
),
overrideArmor = json.armor != null,
armor = json.armor ?: 0,
armor = json.armor ?: defaultArmor(),
overrideLearning = json.learning != null,
learning = json.learning ?: defaultLearning(intelligence = json.intelligence),
overrideHpGrow = json.hpGrowf != null,
hpGrow = json.hpGrowf ?: defaultHpGrow(constitution = json.constitution),
commonSkills = json.skills.map {
CharacterSheet.Skill(
id = it.id,
@ -179,6 +166,5 @@ class CharacterSheetJsonFactory(
)
},
)
return sheet
}
}

View file

@ -24,6 +24,10 @@ data class CharacterSheet(
val damageBonus: String,
val overrideArmor: Boolean,
val armor: Int,
val overrideLearning: Boolean,
val learning: Int,
val overrideHpGrow: Boolean,
val hpGrow: Int,
// skills
val commonSkills: List<Skill>,
val specialSkills: List<Skill>,
@ -80,5 +84,7 @@ data class CharacterSheet(
const val PP = "PP"
const val DMG = "DMG"
const val ARMOR = "ARMOR"
const val LB = "LEARNING"
const val GHP = "HP_GROW"
}
}

View file

@ -22,6 +22,8 @@ data class CharacterSheetJsonV1(
val maxPP: Int?,
val damageBonus: String?,
val armor: Int?,
val learning: Int?,
val hpGrowf: Int?,
// skills
val skills: List<Skill>,
// occupations

View file

@ -18,6 +18,8 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet__charact
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__armor
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__damage_bonus
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__hit_point
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__hp_grow
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__learning
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__movement
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__power_point
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__charisma
@ -30,6 +32,8 @@ import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__armor
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__bonus_damage
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__hit_point
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__hp_grow
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__learning
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__movement
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__power_point
import org.jetbrains.compose.resources.getString
@ -171,6 +175,26 @@ class CharacterSheetFactory(
),
editable = false,
),
Characteristic(
id = CharacteristicId.LB,
label = getString(Res.string.character_sheet__sub_characteristics__learning),
value = "${sheet.learning}",
tooltips = TooltipUio(
title = getString(Res.string.character_sheet__sub_characteristics__learning),
description = getString(Res.string.tooltip__sub_characteristics__learning),
),
editable = false,
),
Characteristic(
id = CharacteristicId.GHP,
label = getString(Res.string.character_sheet__sub_characteristics__hp_grow),
value = "${sheet.hpGrow}",
tooltips = TooltipUio(
title = getString(Res.string.character_sheet__sub_characteristics__hp_grow),
description = getString(Res.string.tooltip__sub_characteristics__hp_grow),
),
editable = false,
),
),
commonSkills = sheet.commonSkills.map { skill ->
Node(

View file

@ -3,8 +3,7 @@ package com.pixelized.desktop.lwa.screen.characterSheet.edit
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import com.pixelized.desktop.lwa.business.DamageBonusUseCase
import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase
import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
import com.pixelized.desktop.lwa.repository.characterSheet.SkillDescriptionFactory
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
import com.pixelized.desktop.lwa.screen.characterSheet.edit.common.SkillFieldFactory
@ -45,27 +44,26 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sk
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__throw
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__armor
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__damage_bonus
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__hit_point
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__hp_grow
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__learning
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__max_hit_point
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__max_power_point
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__movement
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__power_point
import org.jetbrains.compose.resources.getString
import java.util.UUID
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min
class CharacterSheetEditFactory(
private val bonusDamageUseCase: DamageBonusUseCase,
private val characterSheetUseCase: CharacterSheetUseCase,
private val skillFieldFactory: SkillFieldFactory,
private val skillDescriptionFactory: SkillDescriptionFactory,
private val normalizer: SkillNormalizerUseCase,
) {
suspend fun updateCharacterSheet(
currentSheet: CharacterSheet?,
editedSheet: CharacterSheetEditPageUio,
): CharacterSheet {
val editedMaxHp = editedSheet.maxHp.unpack()?.toIntOrNull() ?: currentSheet?.maxHp ?: 0
val editedMaxPp = editedSheet.maxPp.unpack()?.toIntOrNull() ?: currentSheet?.maxPp ?: 0
return CharacterSheet(
id = editedSheet.id,
name = editedSheet.name.value.value,
@ -95,19 +93,11 @@ class CharacterSheetEditFactory(
?: currentSheet?.movement
?: 10,
overrideMaxHp = editedSheet.maxHp.value.value.value.isNotBlank(),
maxHp = editedSheet.maxHp.unpack()?.toIntOrNull()
?: currentSheet?.maxHp
?: 0,
currentHp = editedSheet.currentHp.unpack()?.toIntOrNull()
?: currentSheet?.currentHp
?: 0,
maxHp = editedMaxHp,
currentHp = currentSheet?.currentHp?.coerceAtMost(editedMaxHp) ?: editedMaxHp,
overrideMaxPP = editedSheet.maxPp.value.value.value.isNotBlank(),
maxPp = editedSheet.maxPp.unpack()?.toIntOrNull()
?: currentSheet?.maxPp
?: 0,
currentPp = editedSheet.currentPp.unpack()?.toIntOrNull()
?: currentSheet?.currentPp
?: 0,
maxPp = editedMaxPp,
currentPp = currentSheet?.currentPp?.coerceAtMost(editedMaxPp) ?: editedMaxPp,
overrideDamageBonus = editedSheet.damageBonus.value.value.value.isNotBlank(),
damageBonus = editedSheet.damageBonus.unpack()
?: currentSheet?.damageBonus
@ -116,6 +106,10 @@ class CharacterSheetEditFactory(
armor = editedSheet.armor.unpack()?.toIntOrNull()
?: currentSheet?.armor
?: 0,
overrideLearning = editedSheet.learning.value.value.value.isNotBlank(),
learning = editedSheet.learning.unpack()?.toIntOrNull() ?: 0,
overrideHpGrow = editedSheet.hpGrow.value.value.value.isNotBlank(),
hpGrow = editedSheet.hpGrow.unpack()?.toIntOrNull() ?: 0,
commonSkills = editedSheet.commonSkills.map { editedSkill ->
val currentSkill = currentSheet?.commonSkills?.firstOrNull {
it.id == editedSkill.id
@ -236,239 +230,243 @@ class CharacterSheetEditFactory(
val specialSkillsLabel = getString(Res.string.character_sheet_edit__skills__special_title)
val magicSkillsLabel = getString(Res.string.character_sheet_edit__skills__magic_title)
val maxHitPoint = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__max_hit_point),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else "",
placeholder = derivedStateOf { "${ceil((con() + hei()) / 2f).toInt()}" },
)
)
val maxPowerPoint = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__max_power_point),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideMaxPP == true) "${sheet.maxPp}" else "",
placeholder = derivedStateOf { "${pow()}" },
)
)
return CharacterSheetEditPageUio(
id = sheet?.id ?: UUID.randomUUID().toString(),
name = skillFieldFactory.createWrapper(
label = mutableStateOf(getString(Res.string.character_sheet_edit__name_label)),
value = sheet?.name ?: ""
),
strength = str,
dexterity = dex,
constitution = con,
height = hei,
intelligence = int,
power = pow,
charisma = cha,
movement = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__movement),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideMovement == true) "${sheet.movement}" else "",
placeholder = mutableStateOf("10"),
)
),
maxHp = maxHitPoint,
currentHp = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__hit_point),
value = skillFieldFactory.createWrapper(
enable = false,
placeholder = derivedStateOf {
val min = min(
sheet?.currentHp ?: Int.MAX_VALUE,
maxHitPoint.unpack()?.toIntOrNull() ?: Int.MAX_VALUE,
)
if (min != Int.MAX_VALUE) "$min" else ""
},
)
),
maxPp = maxPowerPoint,
currentPp = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__power_point),
value = skillFieldFactory.createWrapper(
enable = false,
placeholder = derivedStateOf {
val min = min(
sheet?.currentPp ?: Int.MAX_VALUE,
maxPowerPoint.unpack()?.toIntOrNull() ?: Int.MAX_VALUE,
)
if (min != Int.MAX_VALUE) "$min" else ""
},
)
),
damageBonus = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideDamageBonus == true) sheet.damageBonus else "",
placeholder = derivedStateOf {
bonusDamageUseCase.bonusDamage(
strength = str(),
height = hei()
)
},
)
),
armor = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__armor),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideArmor == true) "${sheet.armor}" else "",
placeholder = mutableStateOf("0"),
)
),
commonSkills = listOf(
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.COMBAT_ID,
label = getString(Res.string.character_sheet_edit__skills__combat),
base = derivedStateOf { normalizer.normalize(dex() * 2) },
return with(characterSheetUseCase) {
CharacterSheetEditPageUio(
id = sheet?.id ?: UUID.randomUUID().toString(),
name = skillFieldFactory.createWrapper(
label = mutableStateOf(getString(Res.string.character_sheet_edit__name_label)),
value = sheet?.name ?: ""
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.DODGE_ID,
label = getString(Res.string.character_sheet_edit__skills__dodge),
base = derivedStateOf { normalizer.normalize(dex() * 2) },
strength = str,
dexterity = dex,
constitution = con,
height = hei,
intelligence = int,
power = pow,
charisma = cha,
movement = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__movement),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideMovement == true) "${sheet.movement}" else "",
placeholder = derivedStateOf {
"${characterSheetUseCase.defaultMovement()}"
},
)
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.GRAB_ID,
label = getString(Res.string.character_sheet_edit__skills__grab),
base = derivedStateOf { normalizer.normalize(str() + hei()) },
maxHp = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__max_hit_point),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else "",
placeholder = derivedStateOf {
"${
characterSheetUseCase.defaultMaxHp(
constitution = con(),
height = hei()
)
}"
},
)
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.THROW_ID,
label = getString(Res.string.character_sheet_edit__skills__throw),
base = derivedStateOf { normalizer.normalize(str() + dex()) },
maxPp = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__max_power_point),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideMaxPP == true) "${sheet.maxPp}" else "",
placeholder = derivedStateOf {
"${characterSheetUseCase.defaultMaxPower(power = pow())}"
},
)
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.ATHLETICS_ID,
label = getString(Res.string.character_sheet_edit__skills__athletics),
base = derivedStateOf { normalizer.normalize(str() + con() * 2) },
damageBonus = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideDamageBonus == true) sheet.damageBonus else "",
placeholder = derivedStateOf {
characterSheetUseCase.defaultDamageBonus(
strength = str(),
height = hei()
)
},
)
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.ACROBATICS_ID,
label = getString(Res.string.character_sheet_edit__skills__acrobatics),
base = derivedStateOf { normalizer.normalize(dex() + con() * 2) },
armor = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__armor),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideArmor == true) "${sheet.armor}" else "",
placeholder = derivedStateOf {
"${characterSheetUseCase.defaultArmor()}"
},
)
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.PERCEPTION_ID,
label = getString(Res.string.character_sheet_edit__skills__perception),
base = derivedStateOf { normalizer.normalize(10 + int() * 2) },
learning = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__learning),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideLearning == true) "${sheet.learning}" else "",
placeholder = derivedStateOf {
"${characterSheetUseCase.defaultLearning(intelligence = int())}"
},
)
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.SEARCH_ID,
label = getString(Res.string.character_sheet_edit__skills__search),
base = derivedStateOf { normalizer.normalize(10 + int() * 2) },
hpGrow = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__hp_grow),
value = skillFieldFactory.createWrapper(
value = if (sheet?.overrideHpGrow == true) "${sheet.hpGrow}" else "",
placeholder = derivedStateOf {
"${characterSheetUseCase.defaultHpGrow(constitution = con())}"
},
)
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.EMPATHY_ID,
label = getString(Res.string.character_sheet_edit__skills__empathy),
base = derivedStateOf { normalizer.normalize(cha() + int()) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.PERSUASION_ID,
label = getString(Res.string.character_sheet_edit__skills__persuasion),
base = derivedStateOf { normalizer.normalize(cha() * 3) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.INTIMIDATION_ID,
label = getString(Res.string.character_sheet_edit__skills__intimidation),
base = derivedStateOf { normalizer.normalize(cha() + max(pow(), hei()) * 2) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.SPIEL_ID,
label = getString(Res.string.character_sheet_edit__skills__spiel),
base = derivedStateOf { normalizer.normalize(cha() * 2 + int()) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.BARGAIN_ID,
label = getString(Res.string.character_sheet_edit__skills__bargain),
base = derivedStateOf { normalizer.normalize(cha() * 2) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.DISCRETION_ID,
label = getString(Res.string.character_sheet_edit__skills__discretion),
base = derivedStateOf { normalizer.normalize(cha() + dex() * 2 - hei()) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.SLEIGHT_OF_HAND_ID,
label = getString(Res.string.character_sheet_edit__skills__sleight_of_hand),
base = derivedStateOf { normalizer.normalize(dex() * 2) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.AID_ID,
label = getString(Res.string.character_sheet_edit__skills__aid),
base = derivedStateOf { normalizer.normalize(int() + dex()) },
),
),
specialSkills = sheet?.specialSkills?.map { skill ->
skillFieldFactory.createSkill(
id = skill.id,
label = specialSkillsLabel,
descriptionValue = skill.description ?: "",
labelValue = skill.label,
baseValue = skill.base,
bonusValue = skill.bonus ?: "",
levelValue = skill.level ?: "",
options = run {
val current = sheet.specialSkills.firstOrNull { it.id == skill.id }
listOf(
skillFieldFactory.occupationOption(checked = current?.occupation ?: false),
skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
)
},
)
} ?: emptyList(),
magicSkills = sheet?.magicSkills?.map { skill ->
skillFieldFactory.createSkill(
id = skill.id,
label = magicSkillsLabel,
descriptionValue = skill.description ?: "",
labelValue = skill.label,
baseValue = skill.base,
bonusValue = skill.bonus ?: "",
levelValue = skill.level ?: "",
options = run {
val current = sheet.magicSkills.firstOrNull { it.id == skill.id }
listOf(
skillFieldFactory.occupationOption(
checked = current?.occupation ?: false
),
skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
)
},
)
} ?: emptyList(),
actions = sheet?.actions?.map { action ->
ActionFieldUio(
id = action.id,
label = skillFieldFactory.createWrapper(
label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__name_label)),
value = action.label,
commonSkills = listOf(
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.COMBAT_ID,
label = getString(Res.string.character_sheet_edit__skills__combat),
base = derivedStateOf { normalize(dex() * 2) },
),
action = skillFieldFactory.createWrapper(
label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__action_label)),
value = action.roll,
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.DODGE_ID,
label = getString(Res.string.character_sheet_edit__skills__dodge),
base = derivedStateOf { normalize(dex() * 2) },
),
option = skillFieldFactory.deleteOption { onDeleteSkill(action.id) },
)
} ?: emptyList(),
)
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.GRAB_ID,
label = getString(Res.string.character_sheet_edit__skills__grab),
base = derivedStateOf { normalize(str() + hei()) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.THROW_ID,
label = getString(Res.string.character_sheet_edit__skills__throw),
base = derivedStateOf { normalize(str() + dex()) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.ATHLETICS_ID,
label = getString(Res.string.character_sheet_edit__skills__athletics),
base = derivedStateOf { normalize(str() + con() * 2) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.ACROBATICS_ID,
label = getString(Res.string.character_sheet_edit__skills__acrobatics),
base = derivedStateOf { normalize(dex() + con() * 2) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.PERCEPTION_ID,
label = getString(Res.string.character_sheet_edit__skills__perception),
base = derivedStateOf { normalize(10 + int() * 2) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.SEARCH_ID,
label = getString(Res.string.character_sheet_edit__skills__search),
base = derivedStateOf { normalize(10 + int() * 2) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.EMPATHY_ID,
label = getString(Res.string.character_sheet_edit__skills__empathy),
base = derivedStateOf { normalize(cha() + int()) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.PERSUASION_ID,
label = getString(Res.string.character_sheet_edit__skills__persuasion),
base = derivedStateOf { normalize(cha() * 3) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.INTIMIDATION_ID,
label = getString(Res.string.character_sheet_edit__skills__intimidation),
base = derivedStateOf { normalize(cha() + max(pow(), hei()) * 2) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.SPIEL_ID,
label = getString(Res.string.character_sheet_edit__skills__spiel),
base = derivedStateOf { normalize(cha() * 2 + int()) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.BARGAIN_ID,
label = getString(Res.string.character_sheet_edit__skills__bargain),
base = derivedStateOf { normalize(cha() * 2) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.DISCRETION_ID,
label = getString(Res.string.character_sheet_edit__skills__discretion),
base = derivedStateOf { normalize(cha() + dex() * 2 - hei()) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.SLEIGHT_OF_HAND_ID,
label = getString(Res.string.character_sheet_edit__skills__sleight_of_hand),
base = derivedStateOf { normalize(dex() * 2) },
),
createBaseSkill(
sheet = sheet,
id = CharacterSheet.CommonSkillId.AID_ID,
label = getString(Res.string.character_sheet_edit__skills__aid),
base = derivedStateOf { normalize(int() + dex()) },
),
),
specialSkills = sheet?.specialSkills?.map { skill ->
skillFieldFactory.createSkill(
id = skill.id,
label = specialSkillsLabel,
descriptionValue = skill.description ?: "",
labelValue = skill.label,
baseValue = skill.base,
bonusValue = skill.bonus ?: "",
levelValue = skill.level ?: "",
options = run {
val current = sheet.specialSkills.firstOrNull { it.id == skill.id }
listOf(
skillFieldFactory.occupationOption(current?.occupation ?: false),
skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
)
},
)
} ?: emptyList(),
magicSkills = sheet?.magicSkills?.map { skill ->
skillFieldFactory.createSkill(
id = skill.id,
label = magicSkillsLabel,
descriptionValue = skill.description ?: "",
labelValue = skill.label,
baseValue = skill.base,
bonusValue = skill.bonus ?: "",
levelValue = skill.level ?: "",
options = run {
val current = sheet.magicSkills.firstOrNull { it.id == skill.id }
listOf(
skillFieldFactory.occupationOption(
checked = current?.occupation ?: false
),
skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
)
},
)
} ?: emptyList(),
actions = sheet?.actions?.map { action ->
ActionFieldUio(
id = action.id,
label = skillFieldFactory.createWrapper(
label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__name_label)),
value = action.label,
),
action = skillFieldFactory.createWrapper(
label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__action_label)),
value = action.roll,
),
option = skillFieldFactory.deleteOption { onDeleteSkill(action.id) },
)
} ?: emptyList(),
)
}
}
private suspend fun createBaseSkill(

View file

@ -70,10 +70,10 @@ data class CharacterSheetEditPageUio(
val movement: SimpleFieldUio,
val maxHp: SimpleFieldUio,
val maxPp: SimpleFieldUio,
val currentHp: SimpleFieldUio,
val currentPp: SimpleFieldUio,
val damageBonus: SimpleFieldUio,
val armor: SimpleFieldUio,
val learning: SimpleFieldUio,
val hpGrow: SimpleFieldUio,
val commonSkills: List<BaseSkillFieldUio>,
val specialSkills: List<SkillFieldUio>,
val magicSkills: List<SkillFieldUio>,
@ -94,11 +94,11 @@ data class CharacterSheetEditPageUio(
get() = listOf(
movement,
maxHp,
currentHp,
maxPp,
currentPp,
damageBonus,
armor,
learning,
hpGrow,
)
}

View file

@ -6,43 +6,45 @@ class DamageBonusUseCaseTest {
@Test
fun testBonusDamage() {
val userCase = CharacterSheetUseCase()
(0 until 12).forEach {
val result = DamageBonusUseCase.bonusDamage(stat = it)
val result = userCase.defaultDamageBonus(sum = it)
val expected = "-1d6"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
}
}
(12 until 18).forEach {
val result = DamageBonusUseCase.bonusDamage(stat = it)
val result = userCase.defaultDamageBonus(sum = it)
val expected = "-1d4"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
}
}
(18 until 23).forEach {
val result = DamageBonusUseCase.bonusDamage(stat = it)
val result = userCase.defaultDamageBonus(sum = it)
val expected = "+0"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
}
}
(23 until 30).forEach {
val result = DamageBonusUseCase.bonusDamage(stat = it)
val result = userCase.defaultDamageBonus(sum = it)
val expected = "+1d4"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
}
}
(30 until 40).forEach {
val result = DamageBonusUseCase.bonusDamage(stat = it)
val result = userCase.defaultDamageBonus(sum = it)
val expected = "+1d6"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
}
}
(40 until 100).forEach {
val result = DamageBonusUseCase.bonusDamage(stat = it)
val result = userCase.defaultDamageBonus(sum = it)
val expected = "+2d6"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"

View file

@ -5,7 +5,7 @@ import org.junit.Test
class RollUseCaseTest {
companion object {
private const val ROLL_COUNT = 1000000000
private const val ROLL_COUNT = 100000000 // 100*10^6
}
@Test
@ -20,16 +20,18 @@ class RollUseCaseTest {
@Test
fun testRoll1D100_() {
val result = build1D100ResultSet()
val results = build1D100ResultSet()
val delta = 0.001f
val delta = 0.005f
val median = (ROLL_COUNT / 100).let {
(it * (1f - delta)).toInt()..(it * (1f + delta)).toInt()
}
println("Testing if with $ROLL_COUNT rolls we have at least all results in $median.")
assert(result.all { it in median }) {
"Maybe a false negative, we expected that all values should be in $median a result.\nroll amount: $ROLL_COUNT - result:$result"
results.map { it in median }.forEachIndexed { index, result ->
assert(result) {
"Maybe a false negative, we expected that all values should be in $median a result.\nroll amount: $ROLL_COUNT - index:$index result:${results[index]}"
}
}
}
@ -37,7 +39,7 @@ class RollUseCaseTest {
val useCase = RollUseCase()
val result = MutableList(100) { 0 }
repeat(count) {
val roll = useCase.rollD100()
val roll = useCase.roll(faces = 100)
result[roll - 1] += 1
}
return result

View file

@ -6,7 +6,8 @@ class SkillNormalizerUseCaseText {
@Test
fun testNormalization() {
val useCase = SkillNormalizerUseCase()
val useCase = CharacterSheetUseCase()
val samples = listOf(
0 to 0,
1 to 0,
@ -19,6 +20,96 @@ class SkillNormalizerUseCaseText {
8 to 5,
9 to 5,
10 to 10,
11 to 10,
12 to 10,
13 to 10,
14 to 10,
15 to 15,
16 to 15,
17 to 15,
18 to 15,
19 to 15,
20 to 20,
21 to 20,
22 to 20,
23 to 20,
24 to 20,
25 to 25,
26 to 25,
27 to 25,
28 to 25,
29 to 25,
30 to 30,
31 to 30,
32 to 30,
33 to 30,
34 to 30,
35 to 35,
36 to 35,
37 to 35,
38 to 35,
39 to 35,
40 to 40,
41 to 40,
42 to 40,
43 to 40,
44 to 40,
45 to 45,
46 to 45,
47 to 45,
48 to 45,
49 to 45,
50 to 50,
51 to 50,
52 to 50,
53 to 50,
54 to 50,
55 to 55,
56 to 55,
57 to 55,
58 to 55,
59 to 55,
60 to 60,
61 to 60,
62 to 60,
63 to 60,
64 to 60,
65 to 65,
66 to 65,
67 to 65,
68 to 65,
69 to 65,
70 to 70,
71 to 70,
72 to 70,
73 to 70,
74 to 70,
75 to 75,
76 to 75,
77 to 75,
78 to 75,
79 to 75,
80 to 80,
81 to 80,
82 to 80,
83 to 80,
84 to 80,
85 to 85,
86 to 85,
87 to 85,
88 to 85,
89 to 85,
90 to 90,
91 to 90,
92 to 90,
93 to 90,
94 to 90,
95 to 95,
96 to 95,
97 to 95,
98 to 95,
99 to 95,
100 to 100,
)
samples.forEach { (value, expected) ->
assert(useCase.normalize(value) == expected) {

View file

@ -7,8 +7,9 @@ class SkillStepUseCaseTest {
@Test
fun testStepForSkill() {
val useCase = SkillStepUseCase()
(1..500).forEach { skill ->
val step = SkillStepUseCase.computeSkillStep(
val step = useCase.computeSkillStep(
skill = skill,
)
val expected = expected[skill] ?: error(

View file

@ -13,16 +13,16 @@ class InstructionParserTest {
fun test(
instruction: String,
expectedModifier: Instruction.Dice.Modifier.Dice.Modifier?,
expectedModifier: Instruction.Dice.Modifier?,
expectedQuantity: Int,
expectedFaces: Int,
) {
val dice = parser.parseInstruction(instruction = instruction)
val dice = parser.parse(value = instruction).first()
assert(dice is Instruction.Dice.Dice) {
assert(dice is Instruction.Dice) {
"Instruction should be ArithmeticInstruction.Dice but was: ${dice::class.java.simpleName}"
}
(dice as? Instruction.Dice.Dice)?.let {
(dice as? Instruction.Dice)?.let {
assert(dice.modifier == expectedModifier) {
"$instruction modifier should be:\"$expectedModifier\", but was: ${dice.modifier}"
}
@ -66,14 +66,14 @@ class InstructionParserTest {
val parser = ArithmeticParser()
ArithmeticParser.words.map { instruction ->
val word = parser.parseInstruction(instruction = instruction)
val word = parser.parse(value = instruction).first()
assert(word is Instruction.Word.Word) {
assert(word is Instruction.Word) {
"Instruction should be ArithmeticInstruction.Word but was: ${word::class.java.simpleName}"
}
(word as? Instruction.Word.Word)?.let {
assert(it.name == instruction) {
"Instruction should be $instruction, but was ${it.name}"
(word as? Instruction.Word)?.let {
assert(it.type.name == instruction) {
"Instruction should be $instruction, but was ${it.type.name}"
}
}
}
@ -84,12 +84,12 @@ class InstructionParserTest {
val parser = ArithmeticParser()
"100".let { instruction ->
val flat = parser.parseInstruction(instruction = instruction)
val flat = parser.parse(value = instruction).first()
assert(flat is Instruction.Flat.Flat) {
assert(flat is Instruction.Flat) {
"Instruction should be ArithmeticInstruction.Flat but was: ${flat::class.java.simpleName}"
}
(flat as? Instruction.Flat.Flat)?.let {
(flat as? Instruction.Flat)?.let {
assert("${it.value}" == instruction) {
"Instruction should be $instruction, but was ${it.value}"
}
@ -97,59 +97,42 @@ class InstructionParserTest {
}
}
@Test
fun testFailedInstructionParse() {
val parser = ArithmeticParser()
assertFails(
message = "Instruction parse should failed with UnknownInstruction",
) {
parser.parseInstruction(instruction = "a110")
}
}
@Test
fun testRollParse() {
val parser = ArithmeticParser()
fun test(
arithmetics: Instruction,
expectedSign: Int,
instruction: Instruction,
expectedInstruction: Instruction,
) {
assert(arithmetics.sign == expectedSign) {
"Arithmetic sign should be $expectedSign but was: ${arithmetics.sign}"
}
assert(arithmetics.instruction == expectedInstruction) {
"Arithmetic instruction should be $expectedInstruction but was: ${arithmetics.instruction}"
assert(instruction == expectedInstruction) {
"Arithmetic instruction should be $expectedInstruction but was: $instruction"
}
}
val instructions = parser.parse(value = "1+1d6+2-BDC+BDD")
val instructions = parser.parse(
value = "1+1d6+2-BDC+BDD",
)
test(
arithmetics = instructions[0],
expectedSign = 1,
expectedInstruction = Instruction.Flat(value = 1),
instruction = instructions[0],
expectedInstruction = Instruction.Flat(sign = 1, value = 1),
)
test(
arithmetics = instructions[1],
expectedSign = 1,
expectedInstruction = Instruction.Dice(quantity = 1, faces = 6, modifier = null),
instruction = instructions[1],
expectedInstruction = Instruction.Dice(sign = 1, modifier = null, quantity = 1, faces = 6),
)
test(
arithmetics = instructions[2],
expectedSign = 1,
expectedInstruction = Instruction.Flat(value = 2),
instruction = instructions[2],
expectedInstruction = Instruction.Flat(sign = 1, value = 2),
)
test(
arithmetics = instructions[3],
expectedSign = -1,
expectedInstruction = Instruction.Word.BDC,
instruction = instructions[3],
expectedInstruction = Instruction.Word(sign = -1, type = Instruction.Word.Type.BDC),
)
test(
arithmetics = instructions[4],
expectedSign = 1,
expectedInstruction = Instruction.Word.BDD,
instruction = instructions[4],
expectedInstruction = Instruction.Word(sign = 1, type = Instruction.Word.Type.BDD),
)
}
}