/**********************************************************************
 *
 *   FreeDoko a Doppelkopf-Game
 *    
 *   Copyright (C) 2001-2011  by Diether Knof and Borg Enders
 *
 *   This program is free software; you can redistribute it and/or 
 *   modify it under the terms of the GNU General Public License as 
 *   published by the Free Software Foundation; either version 2 of 
 *   the License, or (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details. 
 *   You can find this license in the file 'gpl.txt'.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
 *   MA  02111-1307  USA
 *
 *  Contact:
 *    Diether Knof dknof@gmx.de
 *    Borg Enders  borg@borgsoft.de
 *
 *********************************************************************/

#include "trickweighting.h"

#include "VirtualGamesInterface.h"
#include "ai.h"
#include "../../party/party.h"
#include "../../game/game.h"
#include "../../game/exception.h"
#include "../../card/trick.h"
#include "../../misc/setting.h"
#include "../../ui/ui.h"

#ifdef BENDERS
#ifndef RELEASE
// whether to print some weighting informations
#define PLAYERCHECK 2
#endif
#endif


/**
 ** -> result
 **
 ** @param      t    current trick
 ** @param      hi   heuristic interface
 **
 ** @return     whether the opposite team can still win the trick
 **
 ** @author     Borg Enders
 **
 ** @version    0.7.8
 **/
bool 
oppositeTeamCanWinTrick(Trick const &t,
                        VirtualGamesInterface const& hi )
{
  bool trickLost = (t.winnerplayer().team() != hi.team());

  // take a look if all players coming in this trick of other team can still win the trick
  for( unsigned i = t.actcardno(); i < hi.game().playerno(); i++ )
    if( maybe_to_team(hi.teamofplayer(t.player_of_card( i ))) != hi.team() )
    {
      trickLost = (trickLost
                   || hi.handofplayer( 
                                      t.player_of_card( i ) 
                                     ).higher_card_exists( t.winnercard() ));
    } // if( maybe_to_team(hi.teamofplayer(t.player_of_card(i))) != hi.team() )
  return trickLost;
} // bool oppositeTeamCanWinTrick ( Trick t, HeuristicInterface hi )


int
TrickWeighting::modi_dolle_swines(VirtualGamesInterface const& vgi,
                                  Trick const& trick,
                                  Team const team,
                                  HandCard const& card,
                                  Team winnerteam,
                                  Ai const& ai)
{
  int modi = 0;

  if( !card.istrump() )
    return modi;

  if (!(   card.isswine()
        || card.ishyperswine()
        || card.isdolle()))
    return modi;

  // have played a very high card


  // 2005-08-06: swines in the last three tricks
  // modi -= 29; // previous values: 23,14,21,24, 29, 33, 35,31
  modi -= (30 - std::max((int)ai.game().played_cards_no() - 9 , 0));
  // previous: 34
  // previous: no()-12

  if (  (static_cast<int>(trick.points()) - card.value()
         < ai.value(Aiconfig::LIMITQUEEN)))
    modi-= 4;

  if ( maybe_to_team(winnerteam) != team)
    modi -= 26;

  if (maybe_to_team(winnerteam) == team)
  {
    if (    // review Reference 260689
        trick.startplayer().no() == vgi.no() )  // serving with a high trump and something potential higher is still out there
    {
      if (    ai.hand().numberofswines() +
          ai.hand().numberofhyperswines() +
          ai.hand().numberof( Card::DOLLE ) != ai.hand().numberoftrumps() )
      {
        modi -= 10;
      }
    }
  }

  if(  (  vgi.no() != trick.winnerplayer().no()
        && !(  trick.cardno_of_player( card.player() ) == 3
             && trick.winnerplayer().team() == vgi.team() )
       )
    )
  {
    modi -= (36 - std::max((int)ai.game().played_cards_no() - 13, 0));
    modi += trick.points()/2;

    if( trick.cardno_of_player( trick.winnerplayer() )
       < trick.cardno_of_player( card.player() )
       || !trick.jabs_cards_before(  card.player() ))
      modi -= 16; // previously 9, 12
  }


  // not for all three cards


  if (  ! card.isdolle()) // so that a dolle is prefered to a swine
    modi -= 8;  //previous values: 2, 7,9

  if (  trick.startplayer().no() == vgi.no() )
  {
    // previous: 12
    modi -= 18;
    if (    ai.hand().numberofswines() +
        ai.hand().numberofhyperswines() +
        ai.hand().numberof( Card::DOLLE ) == ai.hand().numberoftrumps() )
    {

      if( card.isdolle()
         && (ai.game().swines_owner() == NULL
             || ai.teamofplayer( *ai.game().swines_owner() ) == ai.team() )
         && (ai.game().hyperswines_owner() == NULL
             || ai.teamofplayer( *ai.game().hyperswines_owner() ) == ai.team()) )
      {
        modi += 10;
      }
      if( card.isswine()
         && (ai.game().hyperswines_owner() == NULL
             || ai.teamofplayer( *ai.game().hyperswines_owner() ) == ai.team()) )
      {
        modi += 30;
      }
      if( card.ishyperswine() )
      {
        modi += 50;
      }

    } else
    {
      if( GAMETYPE::is_solo( vgi.game().type() )  // reference 246985
         && vgi.game().soloplayer().no() == vgi.no() ) //2do no higher card still in game
        modi += 21;
    }

  }


  if (  trick.cardno_of_player(card.player()) == 1
      && vgi.game().played_no(Card::DOLLE) == 0 //2do before trick
      && card.isdolle()
      && vgi.game().second_dolle_over_first() )
    modi -= 5;



  // depending on data in the trick

  Trick t( trick.startplayer());
  for(unsigned i = 0; i < trick.cardno_of_player(card.player()); i++ )
  {
    t += trick.card( i );
  }

  if (   trick.cardno_of_player(card.player()) == 3 )
  {
    modi -= 21; // previous 18, 20, 24


    if (t.winnerplayer().team() == vgi.team()) { // reference 43530
      modi -= 9; // previous
    }
  }



  if ( ai.value(Aiconfig::LIMITHIGH).less(t.winnercard()) // !oppositeTeamCanWinTrick( t, vgi ) ) 2do XXX
    && t.winnerplayer().team() == team )
    {
      modi -= 26;
      if( GAMETYPE::is_solo( vgi.game().type() )
         && vgi.game().soloplayer().no() != vgi.no() )
        modi -= 4;

#if 0 //2do XXX versuch Bugfix für 125461.Reference.FreeDoko
      if (vgi.no() == playerCheck) {
        COUT << "X " << (ai.hand().numberofswines() +
                         ai.hand().numberofhyperswines() +
                         ai.hand().numberof( Card::DOLLE )) << "/" << ai.hand().numberoftrumps() << " X"  <<endl;
      }

      if(  trick.cardno_of_player(card.player()) == 3
         && (ai.hand().numberofswines() +
             ai.hand().numberofhyperswines() +
             ai.hand().numberof( Card::DOLLE ) < ai.hand().numberoftrumps() )
        )
        modi -= 22;
#endif

    }

  // only for soli
  if( GAMETYPE::is_solo( vgi.game().type() )
     && vgi.game().soloplayer().no() == vgi.no() )
    modi += 3;


  return modi;
}

/**
 **
 ** -> result
 **
 ** @param      vgi	the virtual games interface
 ** @param      trick   the trick to be examined
 ** @param      t	the team which should make points
 ** @param      card    the card played by the player
 **
 ** @return     the weighting of the trick for the team 'team'
 **
 ** @version    0.4.4
 **
 ** @author     Borg Enders
 **
 ** @todo       perhaps points for getting the fox home
 ** @todo       perhaps when playing the highest card, subtract in modi
 **		the distance to the next lower card
 **/

int
TrickWeighting::modi(VirtualGamesInterface const& vgi,
                     Trick const& trick,
                     Team const t,
                     HandCard const& card)
{
  DEBUG_ASSERTION(trick.isfull(),
                  "TrickWeighting::modi()\n"
                  "  trick is not full");
  Game const& game_virt = trick.game();
  Ai const& ai = (dynamic_cast<Ai const*>(&game_virt.player(vgi.no()))
                  ? static_cast<Ai const&>(game_virt.player( vgi.no() ))
                  : static_cast<Ai const&>(vgi.game().player(vgi.no()))
                 );
  //Team const winnerteam = ai.teamofplayer(trick.winnerplayer());
  Team winnerteam
    = ::maybe_to_team(vgi.teamofplayer(trick.winnerplayer()));
  if (winnerteam == TEAM::UNKNOWN)
    winnerteam = ::opposite(t);

  if ((game_virt.type() == GAMETYPE::MARRIAGE)
      && (game_virt.marriage_selector() != MARRIAGE_SELECTOR::TEAM_SET)) {
    // in an undetermined marriage all players shall play for themselves
    if (t == TEAM::RE)
      winnerteam = ::maybe_to_team(ai.teaminfo(trick.winnerplayer()));
    else if (trick.winnerplayer().no() == vgi.no())
      winnerteam = ::maybe_to_team(t);
    else
      winnerteam = ::opposite(::maybe_to_team(t));
  }


  Team const team = ((game_virt.type() == GAMETYPE::MARRIAGE) 
                     ? maybe_to_team(t)
                     : t);

  int modi = 0;


  if (winnerteam == team)
    modi += trick.points();
  else
    modi -= trick.points();

#ifdef PLAYERCHECK
  // Playernumber for which to produce output
  unsigned playerCheck = PLAYERCHECK;


#if 1
  // so in virtual games no informatin is shown
  if (vgi.game().isvirtual())
    playerCheck = 10;
#endif


#endif

#ifdef PLAYERCHECK
  if (vgi.no() == playerCheck) {
    //COUT << trick.game().player(0).hand();
    COUT << '\n';
    COUT << trick << endl;  
    COUT << team << "\t" << trick.winnerplayer().no() << " " << winnerteam << std::endl;
    for( unsigned i = 0; i < ai.game().playerno(); i++ )
      COUT << game_virt.player( i ).team() << "\t";
    COUT << std::endl;
    // 1. block
    COUT << card << "\t" << modi << "\t";
  }
#endif

  if (   (vgi.game().type() == GAMETYPE::SOLO_MEATLESS)
      && ai.no() != vgi.game().soloplayer().no() 
      && vgi.no() != trick.winnerplayer().no()
      && ai.hand().numberof(card.color(), vgi.game()) > 0
      && ai.hand().numberof(card.color(), vgi.game()) < 3
      && (   ai.hand().numberof(Card(card.color(),Card::ACE)) > 0 
          || ai.hand().numberof(Card(card.color(),Card::TEN)) > 0 
          || card.value() == Card::ACE || card.value() == Card::TEN )
     )
  { // prevent non soloplayer from blank playing of cards
    modi -= 12;
  }

  // high cards in meatless 
  if (    vgi.game().type() == GAMETYPE::SOLO_MEATLESS 
      && (    card.value() == Card::ACE 
          || card.value() == Card::TEN )
     )
    modi -= card.value() - 3; 

  if (   (vgi.game().type() == GAMETYPE::MARRIAGE)
      && (vgi.game().marriage_selector() != MARRIAGE_SELECTOR::TEAM_SET)
      && card.value() >= 10 )
    modi -= 9;


  modi += modi_dolle_swines( vgi, trick, t, card, winnerteam, ai );


  if ( card.istrump() && ( card.value() == Card::QUEEN ) )
    modi -= 3; // previous 2
  if (     card.istrump()
      && (card == Card(Card::CLUB, Card::QUEEN) )
     )
  {
    if( vgi.game().teaminfo( ai ) != ai.team() )
    {
      modi += 3; // previous 1
    } else
      modi -= 4; // previous 2, 3
  }

  if ( card.istrump()
      && ( card.value() == Card::QUEEN )
      && (static_cast<int>(trick.points()) - card.value()
          < ai.value(Aiconfig::LIMITQUEEN)))
    modi-= 4; 

  if (   card.istrump()
      && trick.startcard().istrump()
      && !card.less(Card(Card::DIAMOND, Card::QUEEN))
      && (static_cast<int>(trick.points()) >= ai.value(Aiconfig::LIMITQUEEN)) )
  {
    modi += 2;
  }

  if ( card.istrump() 
      && GAMETYPE::is_solo( vgi.game().type() ) )
    modi -= 2;

  if (     card.istrump()
      && ( card.value() == Card::QUEEN 
         )
      && trick.cardno_of_player(card.player()) == 3 )
  {
    modi -= 14; // previous 11, 13, 17

    Trick t( trick.startplayer());
    t += trick.card( 0 );
    t += trick.card( 1 );
    t += trick.card( 2 );

    if (t.winnerplayer().team() == vgi.team()) {
      modi -= 7; // previous

    }
  }

  if ( card.istrump() 
      && card.value() == Card::JACK 
      && trick.cardno_of_player(card.player()) == 3 )
    modi -= 2;


  if(   card.istrump()
     && (  vgi.no() != trick.winnerplayer().no()
         && !(  trick.cardno_of_player( card.player() ) == 3
              && trick.winnerplayer().team() == vgi.team() )
        )
     && ( card.value() == Card::QUEEN )
    )
  {
    modi -= (36 - std::max((int)ai.game().played_cards_no() - 13, 0)); 
    modi += trick.points()/2;

    if( trick.cardno_of_player( trick.winnerplayer() )
       < trick.cardno_of_player( card.player() )
       || !trick.jabs_cards_before(  card.player() )) 
      modi -= 16; // previously 9, 12
  }



  if(  ( vgi.game().type()==GAMETYPE::SOLO_KING  ||
        vgi.game().type()==GAMETYPE::SOLO_KING_JACK ||       
        vgi.game().type()==GAMETYPE::SOLO_KING_QUEEN ||
        vgi.game().type()==GAMETYPE::SOLO_KOEHLER ) &&
     card.value() == Card::KING  )

  {
    if( vgi.no() != trick.winnerplayer().no() )
    {
      modi -= (36 - std::max((int)ai.game().played_cards_no() - 13, 0)); 
      modi += trick.points()/2;

      if( trick.cardno_of_player( trick.winnerplayer() )
         < trick.cardno_of_player( card.player() ) 
         || !trick.jabs_cards_before( card.player() ) )
        modi -= 4;
    } else
      if(     trick.cardno_of_player( card.player() ) == 3
         && trick.points() < 16 )  // reference 131296
      {
        modi -= 25;
      }
  }



  if( !card.istrump()
     &&  vgi.no() != trick.winnerplayer().no() 
     && GAMETYPE::is_solo( vgi.game().type() ) 
     && ( trick.cardno_of_player( trick.winnerplayer() ) > trick.cardno_of_player( vgi.game().soloplayer() ) )
     && !trick.card_of_player( vgi.game().soloplayer() ).less( vgi.trump_card_limit() )
    )
  { 	
    modi -= card.value();
  }

  if( !card.istrump()
     && GAMETYPE::is_solo( vgi.game().type() ) 
     && trick.cardno_of_player( vgi.game().soloplayer() ) == 0 )
  {
    modi += card.value();
    if ( card.value() >= 10 ) 
      modi += 1;
  }


  if( !card.istrump()
     &&  vgi.no() != trick.winnerplayer().no() 
     && GAMETYPE::is_solo( vgi.game().type() ) 
     && ( trick.cardno_of_player( trick.winnerplayer() ) > trick.cardno_of_player( vgi.game().soloplayer() ) )
     && trick.card_of_player( vgi.game().soloplayer() ).less( vgi.trump_card_limit() )
    )
    modi += card.value();



  if( card.istrump()
     && (   vgi.no() != trick.winnerplayer().no()
         || trick.winnercardno() != 3)
     && trick.cardno_of_player(card.player()) == 3 )
  {
    modi -= 2;
    if(  vgi.game().type()!=GAMETYPE::SOLO_KING  &&
       vgi.game().type()!=GAMETYPE::SOLO_QUEEN_JACK &&
       vgi.game().type()!=GAMETYPE::SOLO_KING_JACK &&       
       vgi.game().type()!=GAMETYPE::SOLO_KING_QUEEN &&
       vgi.game().type()!=GAMETYPE::SOLO_KOEHLER  &&
       (card.value() == Card::JACK  || card.value() == Card::QUEEN)  ) // a king is better, but has two points more
      modi -= 3;
  }

  if(  ( vgi.game().type()==GAMETYPE::SOLO_KING  ||
        vgi.game().type()==GAMETYPE::SOLO_KING_JACK ||       
        vgi.game().type()==GAMETYPE::SOLO_KING_QUEEN ||
        vgi.game().type()==GAMETYPE::SOLO_KOEHLER ) &&
     card.value() == Card::KING )
    modi -= 2;


  if(  card.istrump() 
     && (    vgi.game().type()==GAMETYPE::SOLO_KING
         ||  vgi.game().type()==GAMETYPE::SOLO_QUEEN
         ||  vgi.game().type()==GAMETYPE::SOLO_JACK   
        )
    )
    modi -= 4;



  if (!card.istrump()) {
    // prefer color cards a little bit
    if(    card.value() == Card::NINE 
       && trick.winnerplayer().team() != vgi.team() )
      modi += 8; // previous: 6
    if(    card.value() == Card::KING
       && trick.winnerplayer().team() != vgi.team() )
      modi += 4;
  } // if (!card.istrump())

#ifdef PLAYERCHECK	
  if (vgi.no() == playerCheck) {
    // 2. block
    COUT << modi << "\t";
  }
#endif
  // have played a high card
  if ((ai.value(Aiconfig::LIMITHIGH).less(card)
       || ai.value(Aiconfig::LIMITHIGH) == card)
      && (static_cast<int>(trick.points()) - card.value()
          < ai.value(Aiconfig::LIMITQUEEN) ) )
  {
    modi -= 3; 
    if ((2 * ai.hand().numberof_ge(ai.value(Aiconfig::LIMITHIGH))
         < ai.hand().numberoftrumps())
        && (ai.hand().numberof_ge(ai.value(Aiconfig::LIMITHIGH))
            < 3))
      modi -= 13; // previous: 18
  }

  if (   card.istrump()
      && !trick.startcard().istrump()
      && card.less(ai.value(Aiconfig::LIMITHIGH))
      && (static_cast<int>(trick.points()) >= ai.value(Aiconfig::LIMITQUEEN))
      && trick.jabs_cards_before( card.player() ) )
  {
    modi -= 3;
    if ( vgi.color_runs( trick.startcard().color() ) > 0 )
      modi -= 6;
  }



  if( card.isfox() ) // to play a fox it must be worth it
  {
    modi -= 12; // previous 7, 16 (ref 208166)
  }
  if(   card.istrump() 
     && (card.value() == Card::TEN) 
     && (!card.isdolle()) )
  {
    modi -= 8;
  }

  if( card.istrump() && 
     game_virt.next_higher_card( card ).value() != card.value() //2do nect_higher_card_still_in_game compar reference 260689
     && (trick.cardno_of_player(trick.winnerplayer())
         > trick.cardno_of_player(card.player())) 
     && trick.jabs_cards_before( card.player() ))
  { // a higher card in value is needed to jab my card 
    // for example a queen to jab my jack
    modi += 1;
  }


  bool allmyteam=true;

  for( unsigned i = trick.cardno_of_player( ai );
      i < ai.game().playerno();
      i++ )
    allmyteam=allmyteam && ( ai.team() == ::maybe_to_team( vgi.teamofplayer( trick.player_of_card(i) ) ) );

  if (    !card.istrump() 
      && vgi.color_runs( card.color() ) == 0 
      && card.value() == Card::ACE
      && ai.team() == winnerteam
     ) 
  {
    modi += 2;
  }
  if ( !card.istrump()  && card.value() == Card::ACE )
  {

    modi -= 2 - vgi.color_runs( card.color() );
  } else
    if(   card.istrump()
       && card.less( ai.value(Aiconfig::LIMITHIGH) )
       && !trick.startcard().istrump() 
       && (trick.cardno_of_player(trick.winnerplayer())
           > trick.cardno_of_player(card.player())
           && trick.jabs_cards_before( card.player() ) )
       && !(    trick.islastcard()  
            || allmyteam )
      )
    {
      modi -= card.value() * std::min(vgi.color_runs( trick.startcard().color() ),
                                      2u);
    }
  // force enemy with a jack to play a queen
  if (   vgi.no() != trick.winnerplayer().no()
      && (trick.cardno_of_player(trick.winnerplayer())
          > trick.cardno_of_player(card.player())
          && trick.jabs_cards_before( card.player() ) )
      && (card.value() == Card::JACK)
      && (trick.winnercard().value() == Card::QUEEN)
      && (ai.team() != winnerteam)
      && card.istrump()
      && trick.winnercard().istrump() )
    modi += 1;


  // force enemy to play high card
  if (   vgi.no() != trick.winnerplayer().no()
      && (trick.cardno_of_player(trick.winnerplayer())
          > trick.cardno_of_player(card.player())
          && trick.jabs_cards_before( card.player() ) )
      && ai.value(Aiconfig::LIMITHIGH).less(trick.winnercard())
      && ai.team() != winnerteam )
  {
    for (unsigned c = 0; c < trick.actcardno(); c++)
    {
      if (trick.card(c).isfox() )
        modi += 11;
    }

    bool bIsForceTrump = true;
    // ToDo: start with 
    for (unsigned c = trick.cardno_of_player(card.player()) + 1; c < trick.actcardno(); c++)
    {
      if (!trick.card(c).less(card))
        bIsForceTrump = false; 	     
    } // for(c)
    if ( bIsForceTrump )
      modi += 27;
  }



  // show your own team.
  if (    vgi.game().teaminfo( ai ) != ai.team()
      && card == Card::CLUB_QUEEN 
      && ai.hand().numberoftrumps() <= 3 + (ai.hand().has_swines()?0:ai.hand().numberoftrumpaces()) 
      && vgi.game().tricks_remaining_no() - 1 > ai.hand().numberoftrumps() 
      && (trick.cardno_of_player(trick.winnerplayer())
          > trick.cardno_of_player(card.player())
          && trick.jabs_cards_before( card.player() ))
     )
  {
    modi += 4; // previous  
    if (  vgi.game().played_no(Card::CLUB_QUEEN) == 0
        && vgi.game().announcement_of_team( ai.team() ).announcement == ANNOUNCEMENT::NOANNOUNCEMENT )
      modi += 12; // previous 
  }


  // create the teams-vector
  vector<Team> teams;
  for (vector<Player*>::const_iterator
       player = game_virt.players_begin();
       player != game_virt.players_end();
       player++) 
  {
    // determine team of player from ai out of virtual game
    Team const t = ai.teamofplayer( **player );
    if ( t != TEAM::UNKNOWN)
    {
      teams.push_back( maybe_to_team( t ) );
    } else
    {
      teams.push_back( opposite( maybe_to_team(ai.team()) ) );
    }

  } // for (player)

#ifdef PLAYERCHECK	
  if (vgi.no() == playerCheck) {
    // 3. block
    COUT << modi << "\t";

  }
#endif

  if (   !card.istrump() 
      && vgi.no() != trick.winnerplayer().no()
      && winnerteam != team
      && trick.startcard().color() != card.color() 
      && !trick.startcard().istrump() )
  {
    modi -= 8; //previous 6, 16, 14
  }

  if(    !card.istrump()
     && !trick.startcard().istrump()
     && vgi.color_runs( trick.startcard().color() ) > 0 
     && card.color() != trick.startcard().color() 
     && !allmyteam)
    modi -= card.value();






  if (  (vgi.no() != trick.startplayer().no())
      || card.istrump()) {

    if (maybe_to_team(winnerteam) == team)
    {
      Specialpointsvector spv=trick.specialpoints(teams);
      modi += (30
               * Sum_of_Specialpoints(spv,
                                      winnerteam,
                                      trick.startplayer().game()));

      if (   card.isfox() 
          && winnerteam == team
          && ai.value(Aiconfig::LIMITHIGH).less(trick.winnercard()) 
         ) 
        modi += 30; // fox home

    }
    else
    {
      Specialpointsvector spv=trick.specialpoints(teams);
      modi -= (30
               * Sum_of_Specialpoints(spv,
                                      winnerteam,
                                      trick.startplayer().game()));
    }

  } // if (  (vgi.no() != trick.startplayer().no()) || card.istrump())

  // bad style to play fox as first card
  if(    card.isfox() 
     && trick.startplayer().no() == vgi.no() )
  {
    modi -= 90; // previous	
  }

  if(    card.isfox()
     && trick.cardno_of_player(card.player()) == 3
     && maybe_to_team(winnerteam) != team )
  {
    modi -= 6; // previous
  }



  if (  (vgi.no() == trick.startplayer().no())
      && card.istrump())
  {
    modi -= 2;   
  }    



  /// @todo jabbed by player of other team behind me
  if(   !trick.startcard().istrump()
     && vgi.jabbedbyotherteam( trick.startcard().color() )
     && card.value() >= 10 
     && !allmyteam
    )
    modi -= 4;

#ifdef PLAYERCHECK	
  if (vgi.no() == playerCheck) {
    // 4. block
    COUT << modi << "\t";
  }
#endif
  if ((  (vgi.no() != trick.startplayer().no())
       || card.istrump())
     ) {
    for (unsigned c = 0; c < trick.actcardno(); c++) {
      // test, whether the fox has been brought home

      if (trick.card(c).isfox() )
      {

        if(( vgi.game().type() != GAMETYPE::POVERTY || //only for not poverty-player
            vgi.no() != vgi.game().soloplayer().no() ))
        {
          unsigned fact = 25;
          if(   ai.value(Aiconfig::HANDS_KNOWN)  
             || ai.value(Aiconfig::TRUSTING) )
          {
            fact += 10;
            if( card.isfox() )
              fact += 5;
          }
          if( !card.isfox() )
            fact += 5;

          bool allmyteam = true;

          // take a look if all players coming in this trick are of mine team
          for( unsigned i = trick.cardno_of_player( ai ); i < vgi.game().playerno(); i++ )
            allmyteam = allmyteam && ( ai.team() == ai.teaminfo( trick.player_of_card( i ) ) );

          if (    card.isfox()
              && !trick.startcard().istrump()
              && ai.color_runs( trick.startcard().color() ) > 0
              && !allmyteam ) 
          {
            fact -= 21;
          }

          modi += fact * ((team == winnerteam)
                          ? +1
                          : -1);                    

        } else { // fox from above neutralized.
          if ( card.isfox() )
            modi += 30 * ((team != winnerteam)
                          ? +1
                          : 0);
        }
      }
    } // for (c < trick.actcardno())
  } // if (  (vgi.no() != trick.startplayer().no()) || card.istrump())


  //  get large cards of poverty player
  if(( vgi.game().type() == GAMETYPE::POVERTY && //only for not poverty-player
      vgi.no() == vgi.game().poverty_partner().no() ))
  {

    if( (trick.cardno_of_player(vgi.game().soloplayer()) > trick.cardno_of_player(card.player())) // 
       && !card.less(ai.value(Aiconfig::LIMITHIGH))
       &&  card.player().no() != vgi.game().player_previous(vgi.game().soloplayer()).no())
    {
      modi += 21;
      if( ai.value(Aiconfig::LIMITHIGH).less(trick.winnercard()) )
        modi += 5;
      if ( trick.winnercard().isdolle()
          || trick.winnercard().isswine() 
          || trick.winnercard().ishyperswine() )
        modi +=4;
    }
  }

  if ( trick.cardno_of_player(card.player()) == 0
      && (vgi.game().type() == GAMETYPE::MARRIAGE) ) {
    switch (vgi.game().marriage_selector()) {
    case MARRIAGE_SELECTOR::SILENT:
    case MARRIAGE_SELECTOR::TEAM_SET:
      // the marriage is determined
      break;
    case MARRIAGE_SELECTOR::FIRST_COLOR:
    case MARRIAGE_SELECTOR::FIRST_FOREIGN:
      if ( !card.istrump() )
      {
        modi -= 5;
      }
      break;
    case MARRIAGE_SELECTOR::FIRST_TRUMP:
      if ( card.istrump() )
      {
        modi -= 5;
      }
      break;
    case MARRIAGE_SELECTOR::FIRST_CLUB:
      if ( !card.istrump() 
          && card.color() == Card::CLUB )

      {
        modi -= 5;
      }
      break;
    case MARRIAGE_SELECTOR::FIRST_SPADE:
      if ( !card.istrump() 
          && card.color() == Card::SPADE )

      {
        modi -= 5;
      }
      break;
    case MARRIAGE_SELECTOR::FIRST_HEART:
      if ( !card.istrump() 
          && card.color() == Card::HEART )

      {
        modi -= 5;
      }
      break;
    } // switch (this->game().marriage_selector())
  } // if !(marriage && !card is trickstartcard())

  if ( ( card.possible_swine() //2do for a swine possible_swine should return false?
        && !card.isswine() )
      || (  card.possible_hyperswine()
          && !card.ishyperswine()))
    modi += 9;

  if( (ai.hand().numberoftrumps() - 1 <= (vgi.game().tricks_remaining_no() + 1) / 2 )
     && !card.istrump() ) // reference 61146
    modi += 6;

#ifdef PLAYERCHECK

  if (vgi.no() == playerCheck) {

    // 5. block
    COUT << modi << endl;
  }
#endif


  return modi;
} // int WVirtualGames::modi(Trick const& trick, Team const& team, Card const& card)


/**
 ** -> result
 **
 ** @param      vgi         virtual game interface
 ** @param      c           the card played by the player
 ** @param      game_virt   actual virtual game
 **
 ** @return     weighting modifier for getting own team in backhand
 **
 ** @author     Borg Enders
 **
 ** @version    0.6.3
 **/
int
TrickWeighting::backhand(VirtualGamesInterface const& vgi,
                         HandCard const& c,
                         Game const& game_virt )                         
{
  int result = 0;

  // add some points, if the own team is in the back,
  if (game_virt.trick_current_no() < game_virt.trickno() - 1) {
    if (game_virt.player_previous( game_virt.trick_current().winnerplayer() ).team()
        == vgi.team() && !c.isfox() &&
        vgi.game().type() != GAMETYPE::SOLO_MEATLESS )
    {
      result = 5;

      if( game_virt.trick_current().points() > 10 )
        result -= 3;  // Bugreport reference 1236

      if (game_virt.type() == GAMETYPE::POVERTY )
        result -= 3;
    }
    else
      result = -5;

    return result;
  } // if (game_virt.trick_current_no() < game_virt.trickno() - 1)

  return 0;
} // int TrickWeighting::backhand(VirtualGamesInterface vgi, HandCard c, Game game_virt)
