| 110 | } |
| 111 | |
| 112 | void GameTree::buildAction(shared_ptr<ActionNode> root,Rule rule,string last_action,int check_times,int raise_times){ |
| 113 | // current player |
| 114 | int player = root->getPlayer(); |
| 115 | |
| 116 | vector<string> possible_actions; |
| 117 | if(last_action == "roundbegin") { |
| 118 | possible_actions = vector<string>{"check", "bet"}; |
| 119 | }else if(last_action == "begin") { |
| 120 | possible_actions = vector<string>{"check", "bet"}; |
| 121 | }else if(last_action == "bet") { |
| 122 | possible_actions = vector<string>{"call", "raise", "fold"}; |
| 123 | }else if(last_action == "raise") { |
| 124 | possible_actions = vector<string>{"call", "raise", "fold"}; |
| 125 | }else if(last_action == "check") { |
| 126 | possible_actions = vector<string>{"check", "raise", "bet"}; |
| 127 | }else if(last_action == "fold") { |
| 128 | possible_actions = vector<string>{}; |
| 129 | }else if(last_action == "call") { |
| 130 | possible_actions = vector<string>{"check", "raise"}; |
| 131 | }else{ |
| 132 | throw runtime_error(tfm::format("last action %s not found", last_action)); |
| 133 | } |
| 134 | int nextplayer = 1 - player; |
| 135 | |
| 136 | vector<GameActions> actions; |
| 137 | vector<shared_ptr<GameTreeNode>> childrens; |
| 138 | |
| 139 | if (possible_actions.empty()) return; |
| 140 | for (string action : possible_actions) { |
| 141 | if (action == "check") { |
| 142 | // 当不是第一轮的时候 call后面是不能跟check的 |
| 143 | shared_ptr<GameTreeNode> nextnode; |
| 144 | Rule nextrule = Rule(rule); |
| 145 | if ((last_action == "call" && root->getParent() != nullptr && root->getParent()->getParent() == nullptr) || check_times >= 1) { |
| 146 | // 在river check 导致游戏进入showdown |
| 147 | if(rule.current_round == 3){ |
| 148 | double p1_commit = rule.ip_commit; |
| 149 | double p2_commit = rule.oop_commit; |
| 150 | double peace_getback = (p1_commit + p2_commit) / 2; |
| 151 | vector<vector<double>> payoffs(2); |
| 152 | payoffs[0] = {p2_commit, -p2_commit}; |
| 153 | payoffs[1] = {-p1_commit, p1_commit}; |
| 154 | vector<double> peace_getback_vec = {peace_getback - p1_commit, peace_getback - p2_commit}; |
| 155 | nextnode = make_shared<ShowdownNode>(peace_getback_vec,payoffs,GameTreeNode::intToGameRound(rule.current_round),(double)rule.get_pot(),root); |
| 156 | }else { |
| 157 | // 在preflop/flop/turn check 导致游戏进入下一轮 |
| 158 | nextrule.current_round += 1; |
| 159 | nextnode = make_shared<ChanceNode>(nullptr,GameTreeNode::intToGameRound(rule.current_round + 1), rule.get_pot(), root, this->deck.getCards()); |
| 160 | } |
| 161 | }else if (root->getParent() == nullptr) { |
| 162 | nextnode = make_shared<ActionNode>(vector<GameActions>(),vector<shared_ptr<GameTreeNode>>() , nextplayer, GameTreeNode::intToGameRound(rule.current_round), (double) rule.get_pot(), root); |
| 163 | } else { |
| 164 | nextnode = make_shared<ActionNode>(vector<GameActions>(),vector<shared_ptr<GameTreeNode>>() , nextplayer, GameTreeNode::intToGameRound(rule.current_round), (double) rule.get_pot(), root); |
| 165 | } |
| 166 | this->__build(nextnode, nextrule,"check",check_times + 1,0); |
| 167 | actions.push_back(GameActions(GameTreeNode::PokerActions::CHECK,-1)); |
| 168 | childrens.push_back(nextnode); |
| 169 | }else if (action == "bet"){ |
no test coverage detected