void step()

in simple_game/two_suited_bridge.h [87:143]


  void step(int action) override {
    // Any input action has to be legal action. 
    assert(!terminated());

    if (card1_ < 0) {
      // [TODO]: HACK here.
      //   If seqEnumerate is true (e.g. in evaluation mode),
      //   then the environment would alter the nature action to enumerate all
      //   possible
      //        situations (different card1_) and see whether they works.
      if (commOptions_.seqEnumerate) {
        action = numGameFinished_;
      }
      // 0 .. N
      card1_ = action % (commOptions_.N + 1);
      card2_ = action / (commOptions_.N + 1);
      return;
    }

    // Check if bidding is valid.
    if (publicActions_.size() >= 1) {
      if (action > kPass && lastBid_ >= action) {
        // illegal action.
        throw std::runtime_error("action " + std::to_string(action) +
                                 " is not a legal action!");
      } else if (action == kPass) {
        // 1 pass, not initial and we end the game.
        terminated_ = true;
        if (lastBid_ == kPass) {
          // no contract.
          reward_ = 0;
        } else {
          int finalContractLevel = (lastBid_ + 1) / 2;
          int finalContractSuit = lastBid_ % 2;
          int contractReward = 1;
          for (int i = 0; i < finalContractLevel - 1; i++) {
            contractReward <<= 1;
          }
          bool contractMake = false;
          if (((finalContractSuit == 1) && (commOptions_.N + finalContractLevel <= card1_ + card2_)) || 
              ((finalContractSuit == 0) && (commOptions_.N + finalContractLevel <= 2 * commOptions_.N - card1_ - card2_))) {
            contractMake = true;
          }
          if (contractMake) {
            reward_ = contractReward;
          } else {
            // Failed the contract.
            reward_ = -1;
          }
        }
      }
    }
    publicActions_.push_back(action);
    if (action != kPass) {
      lastBid_ = action;
    }
  }