katago_analysis/rules.rs
1use serde::Serialize;
2
3/// Rules settings for KataGo.
4///
5/// See [KataGo's Supported Go Rules](https://lightvector.github.io/KataGo/rules.html) for more details.
6///
7/// ```
8/// # use katago_analysis::*;
9/// let japanese_rules = Rules::japanese();
10/// let bga_rules = Rules::Named("bga".to_string());
11/// let custom_rules = Rules::Explicit {
12/// ko: Ko::Positional,
13/// scoring: Scoring::Territory,
14/// tax: Tax::Seki,
15/// suicide: false,
16/// has_button: false,
17/// white_handicap_bonus: Bonus::Zero,
18/// friendly_pass_ok: true,
19/// };
20/// ```
21#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
22#[serde(untagged, rename_all_fields = "camelCase")]
23pub enum Rules {
24 /// A ruleset identified by name.
25 Named(String),
26
27 /// A ruleset defined by settings for each rule.
28 Explicit {
29 /// The ko rule.
30 ko: Ko,
31
32 /// The scoring method.
33 scoring: Scoring,
34
35 /// The group tax rule.
36 tax: Tax,
37
38 /// Whether multi-stone suicide is legal.
39 suicide: bool,
40
41 /// Whether the button rule is used.
42 has_button: bool,
43
44 /// The bonus points white receives in handicap games.
45 white_handicap_bonus: Bonus,
46
47 /// Whether it's allowed to pass before removing all dead stones.
48 friendly_pass_ok: bool,
49 },
50}
51
52macro_rules! rules {
53 ($(#[$meta:meta])* $name:ident, $value:expr) => {
54 $(#[$meta])*
55 pub fn $name() -> Self {
56 Rules::Named($value.to_string())
57 }
58 };
59}
60
61impl Rules {
62 rules!(
63 /// Japanese and Korean rules.
64 japanese, "japanese"
65 );
66 rules!(
67 /// Chinese rules as implemented over the board (no superko).
68 chinese, "chinese"
69 );
70 rules!(
71 /// Chinese rules as implemented online (positional superko).
72 chinese_ogs, "chinese-ogs"
73 );
74 rules!(
75 /// Stone scoring (area scoring with group tax).
76 stone_scoring, "stone-scoring"
77 );
78 rules!(
79 /// Territory scoring with group tax.
80 ancient_territory, "ancient-territory"
81 );
82 rules!(
83 /// AGA rules using the button.
84 aga_button, "aga-button"
85 );
86 rules!(
87 /// AGA, BGA, and French rules.
88 aga, "aga"
89 );
90 rules!(
91 /// New Zealand rules.
92 new_zealand, "new-zealand"
93 );
94 rules!(
95 /// Tromp-Taylor rules.
96 tromp_taylor, "tromp-taylor"
97 );
98 rules!(
99 /// Ing rules.
100 ing, "ing"
101 );
102}
103
104/// Ko rules.
105#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
106#[serde(rename_all = "UPPERCASE")]
107pub enum Ko {
108 /// The immediately previous position is forbidden.
109 Simple,
110
111 /// Any previous position is forbidden.
112 Positional,
113
114 /// Any previous position with the same player to move is forbidden.
115 Situational,
116}
117
118/// Scoring methods.
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
120#[serde(rename_all = "UPPERCASE")]
121pub enum Scoring {
122 /// Area scoring as used in Chinese rules.
123 Area,
124
125 /// Territory scoring as used in Japanese rules.
126 Territory,
127}
128
129/// Group tax rules.
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
131#[serde(rename_all = "UPPERCASE")]
132pub enum Tax {
133 /// All surrounded empty points count.
134 None,
135
136 /// Empty points surrounded by a group in seki don't count.
137 Seki,
138
139 /// All groups are taxed up to 2 of their surrounded empty points.
140 All,
141}
142
143/// Bonus points white receives in handicap games.
144#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
145pub enum Bonus {
146 /// White receives no bonus points.
147 #[serde(rename = "0")]
148 Zero,
149
150 /// White receives bonus points equal to one less than the number of handicap stones.
151 #[serde(rename = "N-1")]
152 NMinusOne,
153
154 /// White receives bonus points equal to the number of handicap stones.
155 N,
156}