1use bon::Builder;
5use rand::seq::IndexedRandom;
6use serde::{Deserialize, Serialize};
7use std::fmt::Debug;
8use strum::{EnumIs, VariantArray};
9
10#[derive(Builder, Clone, Debug, Deserialize, Serialize)]
11#[serde(rename_all = "camelCase")]
12#[builder(const)]
13pub struct Ethics {
14 power: EthicPowerAxis,
15 truth: EthicTruthAxis,
16}
17
18impl Ethics {
19 pub fn random() -> Self {
20 Self {
21 power: EthicPowerAxis::random(),
22 truth: EthicTruthAxis::random(),
23 }
24 }
25
26 #[inline]
27 pub const fn power(&self) -> EthicPowerAxis {
28 self.power
29 }
30
31 #[inline]
32 pub const fn truth(&self) -> EthicTruthAxis {
33 self.truth
34 }
35
36 #[inline]
37 pub const fn is_militarist(&self) -> bool {
38 self.power.is_militarist()
39 }
40
41 #[inline]
42 pub const fn is_fanatic_militarist(&self) -> bool {
43 self.power.is_fanatic_militarist()
44 }
45
46 #[inline]
47 pub const fn is_pacifist(&self) -> bool {
48 self.power.is_pacifist()
49 }
50
51 #[inline]
52 pub const fn is_fanatic_pacifist(&self) -> bool {
53 self.power.is_fanatic_pacifist()
54 }
55
56 #[inline]
57 pub const fn is_materialist(&self) -> bool {
58 self.truth.is_materialist()
59 }
60
61 #[inline]
62 pub const fn is_fanatic_materialist(&self) -> bool {
63 self.truth.is_fanatic_materialist()
64 }
65
66 #[inline]
67 pub const fn is_spiritualist(&self) -> bool {
68 self.truth.is_spiritualist()
69 }
70
71 #[inline]
72 pub const fn is_fanatic_spiritualist(&self) -> bool {
73 self.truth.is_fanatic_spiritualist()
74 }
75}
76
77impl Default for Ethics {
78 fn default() -> Self {
79 Self::random()
80 }
81}
82
83#[derive(Clone, Copy, Debug, EnumIs, PartialEq, Eq, Deserialize, Serialize, VariantArray)]
84#[serde(rename_all = "kebab-case")]
85pub enum EthicPowerAxis {
86 Militarist,
87 FanaticMilitarist,
88 Pacifist,
89 FanaticPacifist,
90}
91
92impl EthicPowerAxis {
93 pub fn random() -> Self {
94 Self::VARIANTS
95 .choose_weighted(&mut rand::rng(), |ethic| {
96 match ethic {
97 Self::Militarist | Self::Pacifist => 4u8,
98 Self::FanaticMilitarist | Self::FanaticPacifist => 1u8,
99 }
100 })
101 .copied()
102 .expect("`Self::VARIANTS` should never be empty")
103 }
104}
105
106#[derive(Clone, Copy, Debug, EnumIs, PartialEq, Eq, Deserialize, Serialize, VariantArray)]
107#[serde(rename_all = "kebab-case")]
108pub enum EthicTruthAxis {
109 Materialist,
110 FanaticMaterialist,
111 Spiritualist,
112 FanaticSpiritualist,
113}
114
115impl EthicTruthAxis {
116 pub fn random() -> Self {
117 Self::VARIANTS
118 .choose_weighted(&mut rand::rng(), |ethic| {
119 match ethic {
120 Self::Materialist | Self::Spiritualist => 4u8,
121 Self::FanaticMaterialist | Self::FanaticSpiritualist => 1u8,
122 }
123 })
124 .copied()
125 .expect("`Self::VARIANTS` should never be empty")
126 }
127}