/**
   * In the regular mode, this method creates a threaded soccer player. The connection is
   * established once the acknowledging INIT packet is received from the server in the response.
   *
   * <p>In the debug mode this method does half of this job by only sending to the server the
   * CONNECT packet on behalf of one player.
   *
   * @param side
   * @param id
   * @param formation
   */
  private void initPlayer(
      char side, // determines the team
      // this is the suggested player id that can be overridden by the server
      // in the case when the team is spread across different applications;
      // it also determines the role (1 could be the goalie);
      // in the debug mode, server does not change this player id.
      int id,
      Formation formation) {

    String tmpName = id + "-" + side; // used in error messages

    char agentRole;

    if (id == 1 && (useGoalieL && side == 'l' || useGoalieR && side == 'r'))
      agentRole = ConnectData.GOALIE;
    else {
      if (formation.isKicker(id)) agentRole = ConnectData.FIELD_PLAYER_KICKER;
      else agentRole = ConnectData.FIELD_PLAYER;
    }

    // each player object has its own Transceiver
    boolean isServer = false;
    Transceiver transceiver;

    if (debugger == null) {
      // regular mode; create real transceiver communicating over a network
      transceiver = new Transceiver(isServer);
    } else {
      // debug mode; created an emulated transceiver without using a network
      int myport = (side == 'r') ? id : -id;
      transceiver = new DebugTransceiver(isServer, myport, debugger);
      // just send one packet in this mode
      connectToServer(transceiver, tmpName, id, side, agentRole, formation);
      return;
      // <=====
    }

    // regular mode only; trying to connect to server by repeatedly
    // sending the CONNECT packet
    int limit = 0;
    while (limit < 60) {
      // send CONNECT packet
      connectToServer(transceiver, tmpName, id, side, agentRole, formation);
      // wait response from the server and create player agent
      if (initPlayerAgent(transceiver, tmpName, side, agentRole, formation)) {
        try {
          transceiver.setTimeout(0);
        } catch (Exception e) {
          System.out.println(tmpName + " initPlayer fatal error02: " + e);
        }
        return;
        // <=========
      }
      limit++;
    }
    // we get here if things are really bad
    System.out.println(tmpName + " initPlayer failed to connect to server");
  }
  /**
   * This method sends CONNECT packet to server in order to get registered as a player client. In
   * this implementation, the first player is registered as the goalie; the communication protocol
   * allows making goalie registration even from different application; server must take care of
   * getting registered of only one goalie per team
   *
   * @param transceiver
   * @param tmpName
   * @param id
   * @param side
   * @param agentRole
   * @param formation
   */
  protected void connectToServer(
      Transceiver transceiver,
      String tmpName,
      int id,
      char side,
      char agentRole,
      Formation formation) {

    // tell the server on what side this player is, his role, what his
    // real home position is and place all this in a data packet
    char teamside;
    String name;
    if (side == 'l') {
      teamside = ConnectData.LEFT;
      name = teamNameL;
    } else {
      teamside = ConnectData.RIGHT;
      name = teamNameR;
    }

    // System.out.println("My team : " + name );

    ConnectData connectData =
        new ConnectData(
            ConnectData.PLAYER,
            teamside,
            agentRole,
            WorldData.getRealPosOrVel(teamside, formation.getHome(id)),
            name);
    Packet connectPacket = new Packet(Packet.CONNECT, connectData, address, port);

    // attach sender ID for debug purposes
    if (side == 'l') connectPacket.senderIDdebug = -id;
    else connectPacket.senderIDdebug = id;

    // send CONNECT packet to server
    try {
      transceiver.send(connectPacket);

      //			System.out.println(tmpName + " sent connectPacket: "
      //					+ " addr: " + address + " port: " + port + " ::::::  "
      //					+ connectPacket.writePacket() );

      // wait for the acknowledging INIT message from the server
      transceiver.setTimeout(1000);
      return;
    } catch (IOException e) {
      // we get here if things are really bad
      System.out.println("player " + tmpName + " fails to send to server.\n" + e);
      return;
    }
  }
 /**
  * This method creates two soccer team formations based on values of class variables
  * formationTypeL and formationTypeR. Class variables frmLeft and frmRight are the outputs.
  */
 private void initFormations() {
   // create team formations, as necessary
   // leftSize, rightSize could be read from the initialization file
   System.out.println();
   int index_gardien = 0;
   int index_kicker = 0;
   if (leftSize > 0) {
     System.out.println("Set formation for the LEFT team: " + formationTypeL);
     frmLeft = new Formation(formationTypeL.trim(), leftSize, useGoalieL);
     index_gardien = trouveGardien(match.getEquipe1());
     index_kicker = trouveKicker(match.getEquipe1());
     System.out.println(
         ":::::::::::::::::::::: IGoolie : " + index_gardien + " IKicker : " + index_kicker);
     int i = 0;
     boolean kicker = false;
     boolean goalie = false;
     for (Joueur joueur : match.getEquipe1().getJoueur()) {
       FPlayer player = null;
       goalie = false;
       kicker = false;
       if (i == index_kicker) {
         player = PostionneJoueur(joueur, frmLeft, true);
         kicker = true;
       } else player = PostionneJoueur(joueur, frmLeft, false);
       if (i == index_gardien) {
         player.goalie = true;
         goalie = true;
       }
       System.out.println(":::::::::::::::::::::: Kicker : " + kicker + " Goalie : " + goalie);
       frmLeft.add(player);
       i++;
     }
     System.out.println(i + " player(s) are created for left team : " + teamNameL);
   }
   if (rightSize > 0) {
     System.out.println("Set formation for the RIGHT team: " + formationTypeR);
     frmRight = new Formation(formationTypeR.trim(), rightSize, useGoalieR);
     index_gardien = trouveGardien(match.getEquipe2());
     index_kicker = trouveKicker(match.getEquipe2());
     System.out.println(
         ":::::::::::::::::::::: IGoolie : " + index_gardien + " IKicker : " + index_kicker);
     int i = 0;
     boolean kicker = false;
     boolean goalie = false;
     for (Joueur joueur : match.getEquipe2().getJoueur()) {
       FPlayer player = null;
       goalie = false;
       kicker = false;
       if (i == index_kicker) {
         player = PostionneJoueur(joueur, frmRight, true);
         kicker = true;
       } else player = PostionneJoueur(joueur, frmRight, false);
       if (i == index_gardien) {
         player.goalie = true;
         goalie = true;
       }
       System.out.println(":::::::::::::::::::::: Kicker : " + kicker + " Goalie : " + goalie);
       frmRight.add(player);
       i++;
     }
     System.out.println(i + " player(s) are created for right team : " + teamNameR);
   }
   System.out.println();
 }