open_pql/functions/
equity.rs

1use super::*;
2
3#[allow(clippy::cast_precision_loss)]
4#[pqlfn(arg, rtn, eval)]
5pub fn equity(
6    pid: PQLPlayer,
7    street: PQLStreet,
8    (game, board, player_hands, ratings): (
9        PQLGame,
10        Board,
11        &PlayerHands,
12        &mut BufferRatings,
13    ),
14) -> PQLDouble {
15    if street == PQLStreet::River {
16        fill_ratings(PQLStreet::River, (game, board, player_hands, ratings));
17
18        let max = ratings.max();
19
20        if max == ratings[pid] {
21            1.0 / ratings.iter().filter(|r| **r == max).count() as f64
22        } else {
23            0.0
24        }
25    } else if street == PQLStreet::Turn {
26        let mut eq = 0.0;
27        let mut count = 0;
28        for c in Card::ARR_ALL {
29            if board.contains_card(c) || card_in(player_hands, c) {
30                continue;
31            }
32
33            fill_ratings(
34                PQLStreet::River,
35                (game, board.swap_river(c), player_hands, ratings),
36            );
37
38            let max = ratings.max();
39
40            if max == ratings[pid] {
41                eq +=
42                    1.0 / ratings.iter().filter(|r| **r == max).count() as f64;
43            }
44
45            count += 1;
46        }
47
48        eq / f64::from(count)
49    } else {
50        todo!()
51    }
52}
53
54fn card_in(hs: &PlayerHands, c: Card) -> bool {
55    for h in hs {
56        if h.contains(&c) {
57            return true;
58        }
59    }
60
61    false
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use crate::*;
68
69    #[quickcheck]
70    fn test_min_outs_to_hand_type(hbg: HandBoardGame, ht: HandType) {
71        let HandBoardGame {
72            game,
73            hand,
74            board,
75            dead,
76            ..
77        } = hbg;
78
79        let ht = PQLHandType::from((ht, game));
80        let outs =
81            outs_to_hand_type(&hand, PQLStreet::Flop, ht, (game, board, dead));
82
83        assert!(min_outs_to_hand_type(
84            &hand,
85            PQLStreet::Flop,
86            ht,
87            outs.saturating_sub(1),
88            (game, board, dead)
89        ));
90
91        assert!(!min_outs_to_hand_type(
92            &hand,
93            PQLStreet::Flop,
94            ht,
95            outs + 1,
96            (game, board, dead)
97        ));
98    }
99}