1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//! Bot decision-making strategies.
//!
//! The [`BotStrategy`] trait is the single extension point: implement it to
//! create custom AI behaviours. Two built-in strategies are provided:
//!
//! - [`RandomStrategy`] — picks a uniformly random rank from hand and a
//! uniformly random other player as the target.
//! - [`BasicStrategy`] — picks the rank held in the greatest quantity, and
//! targets the most recent other player who has asked for any rank.
pub use BasicStrategy;
pub use RandomStrategy;
use BasicPile;
use cratePlayerAction;
use crate;
/// A pluggable bot decision strategy.
///
/// Implement this trait to define how a bot chooses its next
/// [`PlayerAction::Ask`]. Both [`RandomStrategy`] and [`BasicStrategy`]
/// implement this trait and can be composed via [`crate::bot::BotProfile`].
///
/// # Examples
///
/// ```
/// use cardpack::prelude::{BasicPile, FrenchBasicCard};
/// use gfcore::bot::strategy::{BotStrategy, RandomStrategy};
/// use gfcore::prelude::{AskEntry, Player, PlayerAction, PlayerView};
///
/// let strategy = RandomStrategy;
///
/// // Build a minimal hand and two-player view.
/// let mut hand = BasicPile::default();
/// hand.push(FrenchBasicCard::ACE_SPADES);
///
/// let mut alice = Player::new("Alice");
/// alice.receive_card(FrenchBasicCard::ACE_SPADES);
/// let mut bob = Player::new("Bob");
/// bob.receive_card(FrenchBasicCard::KING_HEARTS);
///
/// let players = PlayerView::from_perspective(&[alice, bob], 0).unwrap();
/// let action = strategy.decide(&hand, &players, &[]);
/// assert!(matches!(action, PlayerAction::Ask { .. }));
/// ```