📄 referee.cc
字号:
else { M_stadium.team_l->pen_taken++; } penalty_check_score();}void PenaltyRef::penalty_foul( Side side ){ if( M_bDebug ) cerr << "penalty_foul " << side << endl; M_stadium.say( ( side == LEFT ) ? "penalty_foul_l" : "penalty_foul_r" ); // if team takes penalty and makes mistake -> miss, otherwise -> score if( side == LEFT && M_cur_pen_taker == LEFT ) penalty_miss( LEFT ); else if( side == RIGHT && M_cur_pen_taker == RIGHT ) penalty_miss( RIGHT ); else if( side == LEFT ) penalty_score( RIGHT ); else penalty_score( LEFT );}void PenaltyRef::penalty_check_score( ){ if( M_bDebug ) cerr << "penalty_check_score" << endl; cerr << "Score: " << ((M_cur_pen_taker == LEFT) ? "*" : " ") << M_stadium.team_l->pen_point << "-" << M_stadium.team_r->pen_point << ((M_cur_pen_taker == RIGHT) ? "*" : " ") << " after " << M_pen_nr_taken << " penalties." << endl; // if both players have taken more than nr_kicks penalties -> check for winner if( M_pen_nr_taken > 2 * ServerParam::instance().pen_nr_kicks ) { if( M_pen_nr_taken % 2 == 0 && M_stadium.team_l->pen_point != M_stadium.team_r->pen_point ) { cerr << "Final score: " << M_stadium.team_l->pen_point << "-" << M_stadium.team_r->pen_point << endl; if( M_stadium.team_l->pen_point > M_stadium.team_r->pen_point ) M_stadium.say( "penalty_winner_l" ); else M_stadium.say( "penalty_winner_r" ); M_stadium.change_play_mode( PM_TimeOver ); } } // if both players have taken nr_kicks and max_extra_kicks penalties -> quit else if( M_pen_nr_taken > 2*( ServerParam::instance().pen_max_extra_kicks + ServerParam::instance().pen_nr_kicks ) ) { cerr << "Final score: " << M_stadium.team_l->pen_point << "-" << M_stadium.team_r->pen_point << endl; if( ServerParam::instance().pen_random_winner ) { if( drand( 0, 1 ) < 0.5 ) { M_stadium.say( "penalty_winner_l" ); M_stadium.team_l->pen_won = true; cerr << "Left team has won the coin toss!" << endl; } else { M_stadium.say( "penalty_winner_r" ); M_stadium.team_r->pen_won = true; cerr << "Right team has won the coin toss!" << endl; } } else M_stadium.say( "penalty_draw" ); M_stadium.change_play_mode( PM_TimeOver ); } // during normal kicks, check whether one team cannot win anymore else { // first calculate how many penalty kick sessions are left // and add this to the current number of points of both teams // finally, subtract 1 point from the team that has already shot this turn int iPenLeft = ServerParam::instance().pen_nr_kicks - M_pen_nr_taken/2; int iMaxExtraLeft = M_stadium.team_l->pen_point + iPenLeft; int iMaxExtraRight = M_stadium.team_r->pen_point + iPenLeft; if( M_pen_nr_taken % 2 == 1 ) { if( M_cur_pen_taker == LEFT ) iMaxExtraLeft--; else if( M_cur_pen_taker == RIGHT ) iMaxExtraRight--; } if( iMaxExtraLeft < M_stadium.team_r->pen_point ) { cerr << "Final score: " << M_stadium.team_l->pen_point << "-" << M_stadium.team_r->pen_point << endl; M_stadium.say( "penalty_winner_r" ); M_stadium.change_play_mode( PM_TimeOver ); } else if( iMaxExtraRight < M_stadium.team_l->pen_point ) { cerr << "Final score: " << M_stadium.team_l->pen_point << "-" << M_stadium.team_r->pen_point << endl; M_stadium.say( "penalty_winner_l" ); M_stadium.change_play_mode( PM_TimeOver ); } }}bool PenaltyRef::penalty_check_players( Side side, int *iPenaltyTaker ){ PlayMode pm = M_stadium.mode; int iOutsideCircle = 0; bool bCheck = true; CArea c( PVector(0.0,0.0), KICK_OFF_CLEAR_DISTANCE ) ; PVector posGoalie; int iPlayerOutside = -1, iGoalieNr=-1; if( pm == PM_PenaltyMiss_Left || pm == PM_PenaltyMiss_Right || pm == PM_PenaltyScore_Left || pm == PM_PenaltyScore_Right ) return true; // for all players from side 'side' get the goalie pos and count how many // players are outside the center circle. for ( int i = 0 ; i < 2 * MAX_PLAYER ; i++) { if (M_stadium.player[i]->alive == DISABLE) continue ; if( M_stadium.player[i]->team->side == side ) { if( M_stadium.player[i]->goalie ) { posGoalie = M_stadium.player[i]->pos; iGoalieNr = i; } else if( ! c.inArea(M_stadium.player[i]->pos) ) { iOutsideCircle++; iPlayerOutside = i; } } } if( iGoalieNr == -1 ) return false; // if the 'side' equals the one that takes the penalty shoot out if( ( side == LEFT && M_cur_pen_taker == LEFT ) || ( side == RIGHT && M_cur_pen_taker == RIGHT ) ) { // in case that goalie takes penalty kick if( iOutsideCircle == 0 ) { if( pm == PM_PenaltySetup_Left || pm == PM_PenaltySetup_Right ) { if( M_stadium.player[iGoalieNr]->pos.distance(M_stadium.ball->pos) > 2.0 ) bCheck = false; else iPlayerOutside = iGoalieNr; } } // if goalie not outside field, check fails else if( fabs(posGoalie.x) < PITCH_LENGTH/2.0 || fabs(posGoalie.y) < PENALTY_AREA_LENGTH/2.0 ) { if( M_bDebug ) cerr << "side " << side << " goalie not correct " << posGoalie.x << " " << posGoalie.y << endl; bCheck = false; } // only one should be outside the circle -> player that takes penalty else if( iOutsideCircle != 1 ) { if( M_bDebug ) cerr << "side " << side << " not 1 player outside " << endl; bCheck = false; } // in setup, player outside circle should be close to ball else if( ( pm == PM_PenaltySetup_Left || pm == PM_PenaltySetup_Right ) && iOutsideCircle == 1 ) { if( M_stadium.player[iPlayerOutside]->pos.distance(M_stadium.ball->pos) > 2.0 ) { if( M_bDebug ) cerr << "side " << side << " attacker not correct "<<endl; bCheck = false; } } } else { // goalie does not stand in front of goal line if( M_stadium.mode != PM_PenaltyTaken_Left && M_stadium.mode != PM_PenaltyTaken_Right ) if( fabs(posGoalie.x) < PITCH_LENGTH/2.0 - ServerParam::instance().pen_max_goalie_dist_x || fabs(posGoalie.y) > GOAL_WIDTH/2.0 ) { if( M_bDebug ) cerr << "side " << side << " goalie to catch not correct " << posGoalie << endl; bCheck = false; } // when receiving the penalty every player should be in center circle if( iOutsideCircle != 0 ) { if( M_bDebug ) cerr << "side " << side << " not everyone in circle "<<endl; bCheck = false; } } if( bCheck == true ) { // if in setup and already in set -> check fails if( ( M_stadium.mode == PM_PenaltySetup_Left && side == LEFT && M_sLeftPenTaken.find(iPlayerOutside) != M_sLeftPenTaken.end() ) || ( M_stadium.mode == PM_PenaltySetup_Right && side == RIGHT && M_sRightPenTaken.find(iPlayerOutside) != M_sRightPenTaken.end() ) ) { if( M_bDebug ) cerr << "side " << side << " same player" << endl; bCheck = false; } } if( iPenaltyTaker != NULL ) *iPenaltyTaker = iPlayerOutside; return bCheck;}void PenaltyRef::penalty_place_all_players( Side side, int *iPenaltyTaker ){ set<int> sPenTaken = (side == LEFT) ? M_sLeftPenTaken : M_sRightPenTaken ; // bool bPlaceKicker = false, bMovedClosestPlayer = false; bool bPenTaken= M_stadium.mode == PM_PenaltyTaken_Right || M_stadium.mode == PM_PenaltyTaken_Left; // if the side equals the one that should take the penalty shootout if( ( side == LEFT && M_cur_pen_taker == LEFT ) || ( side == RIGHT && M_cur_pen_taker == RIGHT ) ) { double dMinDist = -1; int iClosestPlayer = -1; int goalie = -1; // first find the closest player to the ball for ( int i = 0 ; i < 2 * MAX_PLAYER ; i++) { if( M_stadium.player[i]->team->side == side && M_stadium.player[i]->goalie && M_stadium.player[i]->alive != DISABLE && sPenTaken.find( i ) == sPenTaken.end() ) goalie = i; if (M_stadium.player[i]->alive == DISABLE || M_stadium.player[i]->team->side != side || M_stadium.player[i]->goalie || // avoid using the goalie as // a kicker. If there is no // other kicker avilable, // then we will use the // goalie. sPenTaken.find( i ) != sPenTaken.end() ) // players that have // already taken a // kick cannot be // counted as a // potential // kicker. continue; if( dMinDist < 0 || M_stadium.player[i]->pos.distance( M_stadium.ball->pos ) < dMinDist ) { dMinDist = M_stadium.player[i]->pos.distance( M_stadium.ball->pos ); iClosestPlayer = i; } } if( iClosestPlayer < 0 ) // then there was no free player. Pick the goalie { if( goalie < 0 ) // no closest player and no goalie. Very strange { std::cerr << "Could not find kicker\n"; iClosestPlayer = ( side = LEFT ? 0 : 11 ); } else { iClosestPlayer = goalie; } dMinDist = M_stadium.player[ iClosestPlayer ]->pos.distance( M_stadium.ball->pos ); } // for post: iClosestPlayer is the closest player that has not taken a penalty *iPenaltyTaker = iClosestPlayer; // when closest player stands close to the ball and he hasn't taken // a penalty yet, leave him there // the same holds when mode is taken -> we don't want to move kicker// if( sPenTaken.find( iClosestPlayer ) == sPenTaken.end() && // dMinDist < 4.0 )// {// *iPenaltyTaker = iClosestPlayer;// bPlaceKicker = bMovedClosestPlayer = true; // }// else if( bPenTaken == true )// {// bPlaceKicker = bMovedClosestPlayer = true; // *iPenaltyTaker = iClosestPlayer;// } // then replace the players from the specified side for ( int i = 0 ; i < 2 * MAX_PLAYER ; i++) { if (M_stadium.player[i]->alive == DISABLE ) continue; if( i == iClosestPlayer ) { if( dMinDist > 2.0 && !bPenTaken ) { M_stadium.player[i]->pos = PVector(-M_pen_side*(PITCH_LENGTH/2-ServerParam::instance().pen_dist_x-2.0),0); } } else if( M_stadium.player[i]->team->side == side ) { if( M_stadium.player[i]->goalie ) { if( M_stadium.player[i]->pos.y > 0.0 ) { if( M_stadium.player[i]->pos.distance( PVector( -M_pen_side*(PITCH_LENGTH/2+2.0), 25.0 ) ) > 2.0 ) M_stadium.player[i]->pos = PVector( -M_pen_side*(PITCH_LENGTH/2+2.0), 25.0 ); } else // M_stadium.player[i]->pos.y <= 0.0 { if( M_stadium.player[i]->pos.distance( PVector( -M_pen_side*(PITCH_LENGTH/2+2.0), -25.0 ) ) > 2.0 ) M_stadium.player[i]->pos = PVector( -M_pen_side*(PITCH_LENGTH/2+2.0), -25.0 ); } } else // not goalie { CArea center( 0.0, CENTER_CIRCLE_R ); if( !center.inArea( M_stadium.player[i]->pos ) ) M_stadium.player[i]->pos = Polar2PVector( 6.5, i*15 ); } } else // other team { // only move goalie in case the penalty has not been started yet. if( M_stadium.player[i]->goalie ) { if( !bPenTaken ) { if( M_pen_side == LEFT ) { if( M_stadium.player[i]->pos.x - (-PITCH_LENGTH/2.0 + ServerParam::instance().pen_max_goalie_dist_x) > 0 ) M_stadium.player[i]->pos = PVector( -PITCH_LENGTH/2.0 + ServerParam::instance().pen_max_goalie_dist_x - 1.5 ,0 ); } else { if( M_stadium.player[i]->pos.x - (PITCH_LENGTH/2.0 - ServerParam::instance().pen_max_goalie_dist_x) < 0 ) M_stadium.player[i]->pos = PVector( PITCH_LENGTH/2.0 - ServerParam::instance().pen_max_goalie_dist_x + 1.5 ,0 ); } } } else // not goalie { CArea center( 0.0, CENTER_CIRCLE_R ); if( !center.inArea( M_stadium.player[i]->pos ) ) // place other players in circle in penalty area M_stadium.player[i]->pos = Polar2PVector( 6.5, i*15 ); } } } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -