sys/sysmod/openai/basicfuncs/
playtools.rs

1//! ゲームプレイ用のツール。
2
3use crate::sysmod::openai::ParameterType;
4use crate::sysmod::openai::function::{
5    FuncArgs, Function, FunctionTable, ParameterElement, Parameters, get_arg_i64_opt,
6};
7use anyhow::Result;
8use std::collections::HashMap;
9use utils::playtools::dice;
10
11/// このモジュールの関数をすべて登録する。
12pub fn register_all<T: 'static>(func_table: &mut FunctionTable<T>) {
13    register_flip_coin(func_table);
14    register_role_dice(func_table);
15}
16
17/// ダイスまたはコイン数の最小値。
18const COUNT_MIN: i64 = 1;
19/// ダイスまたはコイン数の最大値。
20const COUNT_MAX: i64 = 100;
21/// ダイスの面数の最小値。
22const FACE_MIN: i64 = 1;
23/// ダイスの面数の最大値。
24const FACE_MAX: i64 = 100;
25
26/// コインを投げる。
27async fn flip_coin(args: &FuncArgs) -> Result<String> {
28    let count: i64 = get_arg_i64_opt(args, "count", COUNT_MIN..=COUNT_MAX)?.unwrap_or(1);
29    let result = dice::roll(2_u64, count as u32)?;
30
31    let mut text = String::from("[");
32    let mut first = true;
33    for &n in result.iter() {
34        if first {
35            first = false;
36        } else {
37            text.push(',');
38        }
39        text.push_str(if n == 1 { "\"H\"" } else { "\"T\"" });
40    }
41    text.push(']');
42
43    Ok(text)
44}
45
46fn register_flip_coin<T: 'static>(func_table: &mut FunctionTable<T>) {
47    let mut properties = HashMap::new();
48    properties.insert(
49        "count".to_string(),
50        ParameterElement {
51            type_: vec![ParameterType::Integer, ParameterType::Null],
52            description: Some(format!(
53                "Number of coins ({COUNT_MIN} <= count <= {COUNT_MAX}) (default is 1)"
54            )),
55            //minumum: Some(COUNT_MIN),
56            //maximum: Some(COUNT_MAX),
57            ..Default::default()
58        },
59    );
60
61    func_table.register_function(
62        Function {
63            name: "flip_coin".to_string(),
64            description: Some("Flip coin(s). H means Head. T means Tail.".to_string()),
65            parameters: Parameters {
66                properties,
67                required: vec!["count".to_string()],
68                ..Default::default()
69            },
70            ..Default::default()
71        },
72        |_, _, args| Box::pin(flip_coin(args)),
73    );
74}
75
76/// サイコロを振る。
77async fn role_dice(args: &FuncArgs) -> Result<String> {
78    let face = get_arg_i64_opt(args, "face", FACE_MIN..=FACE_MAX)?.unwrap_or(6);
79    let count = get_arg_i64_opt(args, "count", COUNT_MIN..=COUNT_MAX)?.unwrap_or(1);
80    let result = dice::roll(face as u64, count as u32)?;
81
82    Ok(format!("{result:?}"))
83}
84
85fn register_role_dice<T: 'static>(func_table: &mut FunctionTable<T>) {
86    let mut properties = HashMap::new();
87    properties.insert(
88        "face".to_string(),
89        ParameterElement {
90            type_: vec![ParameterType::Integer, ParameterType::Null],
91            description: Some(format!(
92                "Face count of dice ({FACE_MIN} <= face <= {FACE_MAX}) (default is 6)"
93            )),
94            //minumum: Some(FACE_MIN),
95            //maximum: Some(FACE_MAX),
96            ..Default::default()
97        },
98    );
99    properties.insert(
100        "count".to_string(),
101        ParameterElement {
102            type_: vec![ParameterType::Integer, ParameterType::Null],
103            description: Some(format!(
104                "Number of Dice ({COUNT_MIN} <= count <= {COUNT_MAX}) (default is 1)"
105            )),
106            //minumum: Some(COUNT_MIN),
107            //maximum: Some(COUNT_MAX),
108            ..Default::default()
109        },
110    );
111
112    func_table.register_function(
113        Function {
114            name: "role_dice".to_string(),
115            description: Some(
116                "Role dice with specified number of faces specified number of times".to_string(),
117            ),
118            parameters: Parameters {
119                properties,
120                required: vec!["face".to_string(), "count".to_string()],
121                ..Default::default()
122            },
123            ..Default::default()
124        },
125        |_, _, args| Box::pin(role_dice(args)),
126    );
127}