Index: bb5/arbiter/SPlayer.cc =================================================================== --- bb5/arbiter/SPlayer.cc (rvision 1425) +++ bb5/arbiter/SPlayer.cc (copie de travail) @@ -326,23 +326,15 @@ setHasPlayed(); else setHasBlocked(); - - int mod_st_atk = getSt(); - int mod_st_df = target_->getSt(); - if (mod_st_atk > 2 * mod_st_df || mod_st_df > 2 * mod_st_atk) - nb_block_dices_ = 3; - else if (mod_st_atk != mod_st_df) - nb_block_dices_ = 2; - else - nb_block_dices_ = 1; + int dices = f_->getNbBlockDices(pos_, target_->pos_); + if (dices == 0) { ERR("target undefined or synchronisation error between field and players"); } + nb_block_dices_ = (dices < 0 ? dices * -1 : dices); if (nb_block_dices_ == 1) dice_chooser_id_ = -1; - else if (mod_st_atk < mod_st_df) // Strongest team chooses the dice. - dice_chooser_id_ = r_->getCurrentOpponentTeamId(); else - dice_chooser_id_ = team_id_; + dice_chooser_id_ = (dices < 0 ? r_->getCurrentOpponentTeamId() : team_id_); roll_attempted_ = R_BLOCK; setRerollAvailability(); Index: bb5/common/Field.hh =================================================================== --- bb5/common/Field.hh (rvision 1425) +++ bb5/common/Field.hh (copie de travail) @@ -97,6 +97,24 @@ //! @param pos Position in field to look for. int getNbTackleZones(int team_id, const Position& pos) const; + //! @brief Check if the player can assist a block against another player. + //! @param pos_assister The position of the player assisting. + //! @param team_id The team id of the team that tackles. (ie: The team of the target). + //! @param pos_target The position in field of the target (attacker or defender). + bool canAssist(const Position& pos_assister, int team_id, const Position& pos_target) const; + //! @brief Get the number of supporter avaible for a block. + //! @param pos_assisted Position in field of the player being assisted. + //! @param team_id The team id of the team assister. + //! @param pos_target Position in field of the target (attacker or defender). + int getNbAssister(const Position& pos_assisted, int team_id, const Position& pos_target) const; + //! @brief Get the number of dices to throz during a block. + //! @param pos_attacker Position in field of the player attacking. + //! @param pos_target Position in field of the defender. + //! @return A positif number is returned if his team attacking choose the result, else it is a negative one + //! the absolute value determine the number of dice to roll + int getNbBlockDices(const Position& pos_attacker, const Position& pos_target) const; + + protected: T* tab_[COLS * ROWS]; }; Index: bb5/common/Field.hxx =================================================================== --- bb5/common/Field.hxx (rvision 1425) +++ bb5/common/Field.hxx (copie de travail) @@ -243,7 +243,58 @@ if (intoField(p) && getPlayer(p) != NULL && getPlayer(p)->getTeamId() == team_id - && getPlayer(p)->getStatus() == STA_STANDING) + && getPlayer(p)->getStatus() == STA_STANDING + && getPlayer(p)->hasTackleZone()) res++; return res; } + +template +inline bool Field::canAssist(const Position& pos_assister, int team_id, const Position& pos_target) const +{ + return (pos_assister.isNear(pos_target) + // && (getNbTackleZones(team_id, pos_assister) + // || getPlayer(pos_assister)->hasSkill(SK_GUARD)) + && getNbTackleZones(team_id, pos_assister) == 1 + && getPlayer(pos_assister)->getStatus() == STA_STANDING + && getPlayer(pos_assister)->hasTackleZone()); +} + +template +inline int Field::getNbAssister(const Position& pos_assisted, int team_id, const Position& pos_target) const +{ + int res = 0; + Position p; + + for (p.row = pos_target.row - 1; p.row <= pos_target.row + 1; p.row++) + for (p.col = pos_target.col - 1; p.col <= pos_target.col + 1; p.col++) + if (intoField(p) + && getPlayer(p) != NULL + && p != pos_assisted + && getPlayer(p)->getTeamId() == team_id + && canAssist(p, (team_id*-1)+1, pos_target)) + res++; + return res; +} + +template +inline int Field::getNbBlockDices(const Position& pos_attacker, const Position& pos_target) const +{ + T* attacker; + T* target; + + attacker = getPlayer(pos_attacker); + target = getPlayer(pos_target); + if (attacker == NULL || target == NULL) { + return 0; + } + + // TODO + // When the extra rules (assiting a block) will be implenting the folowing comments could be removed + int mod_st_atk = attacker->getSt(); // + getNbAssister(pos_attacker, attacker->getTeamId(), pos_target); + int mod_st_df = target->getSt(); // + getNbAssister(pos_target, target->getTeamId(), pos_attacker); + + return (mod_st_atk < mod_st_df ? -1 : 1) * + ((mod_st_atk > 2 * mod_st_df || mod_st_df > 2 * mod_st_atk) ? 3 : + (mod_st_atk != mod_st_df ? 2 : 1 )); +} Index: bb5/common/Player.hh =================================================================== --- bb5/common/Player.hh (rvision 1425) +++ bb5/common/Player.hh (copie de travail) @@ -313,6 +313,14 @@ //! @brief Mark the skill as used for this turn. void useSkill(enum eSkill skill); + //! @brief Check if this player has a tacle zone. + bool hasTackleZone() const; + //! @brief Set the 'has lost his tackle zone' marker + //! with skills like "Bone-head" or "Really Stupid". + void lostTackleZone(); + //! @brief Reset the tackle zone marker + void resetTackleZone(); + //! @brief Called on new turn. void resetTurn(); @@ -346,6 +354,8 @@ enum eDeclaredAction action_; bool will_prone_; + bool has_tackle_zone_; + private: SkillList skill_list_; ///< List of skills that this player have. SkillList used_skill_list_; ///< List of skills that this player have used this turn. Index: bb5/common/Player.hxx =================================================================== --- bb5/common/Player.hxx (rvision 1425) +++ bb5/common/Player.hxx (copie de travail) @@ -26,7 +26,8 @@ has_blocked_(false), has_played_(false), action_(DCL_UNASSIGNED), - will_prone_(false) + will_prone_(false), + has_tackle_zone_(true) { name_ = packetToString(m->name); @@ -152,6 +153,7 @@ ma_remain_ = ma_; used_skill_list_.clear(); will_prone_ = (status_ == STA_STUNNED); + resetTackleZone(); } inline const char* Player::stringify(enum eStatus status) @@ -221,3 +223,18 @@ os << std::endl; return os; } + +inline bool Player::hasTackleZone() const +{ + return has_tackle_zone_; +} + +inline void Player::lostTackleZone() +{ + has_tackle_zone_=false; +} + +inline void Player::resetTackleZone() +{ + has_tackle_zone_=true; +} Index: bb5/client/Api.hxx =================================================================== --- bb5/client/Api.hxx (rvision 1425) +++ bb5/client/Api.hxx (copie de travail) @@ -691,20 +691,10 @@ || p->getTeamId() == selected_player_->getTeamId()) return INVALID_ACTION; - // FIXME: Factorize the code to common/ since SPlayer uses the same. - if (selected_player_->getSt() == p->getSt()) - return blockDicesNumberPadding() + 1; + int dices = rules_->field_->getNbBlockDices(selected_player_->getPosition(), to); + if (dices == 0) { ERR("target undefined or synchronisation error between field and players"); } - if (selected_player_->getSt() > 2 * p->getSt()) - return blockDicesNumberPadding() + 3; - - if (selected_player_->getSt() * 2 < p->getSt()) - return blockDicesNumberPadding() - 3; - - if (selected_player_->getSt() > p->getSt()) - return blockDicesNumberPadding() + 2; - else - return blockDicesNumberPadding() - 2; + return blockDicesNumberPadding() + dices; } inline int Api::blockDicesNumberPadding() const