⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 game.java

📁 ErGo是一个很早的Java通用围棋服务器(IGS/NNGS)客户端程序。有全部源码和文档
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
      --nmoves;
    }
    while (currentMove != root
	   && nmoves != 0
	   && !(stopAtBranch && currentMove.isBranch()));
  }
  
  // This version goes back to the given move, or to the beginning if the
  // given move isn't found.
  public void goBackward (Move m) {
    while (currentMove != root && currentMove != m) {
      backup(true);
    }
  }

  /*
   * Go forward (locally only) to a later move.
   * nmoves is the number of moves to go forward.
   * If nmoves = -1 then go to end.
   * variation is the child move to use.  (This is useful in case
   *   the move we start at has variations and the user has just
   *   chosen one.)
   * If variation is null then use the trunk, currentMove.child().
   * If stopAtBranch is true then stop going forward if a move with
   *   variations is encountered, else use main branch.
   * If stopAtMove is non-null then stop if that move is encountered.
   *   The move is compared with ==, not EQUALS.
   */
  public void goForward (int nmoves, Move variation, boolean stopAtBranch,
			 Move stopAtMove, boolean stopAtKibitz) {
    if (currentMove != finalMove()) {
      if (variation != null && currentMove.isVariation(variation)) {
	placeMove(variation, null, true, false);
	nmoves--;
      }
      for (Move next = currentMove.child();
	   next != null && nmoves != 0;
	   nmoves--) {
	placeMove(next, null, true, false);
	if (next == stopAtMove
	    || (stopAtBranch && next != null && next.isBranch())
	    || (stopAtKibitz && next != null && next.hasKibitzes()))
	  break;
	next = next.child();
      }
    }
  }
  
  /**
   * Go to the end of the current branch.
   **/
  public void goToEnd () {
    goForward(-1, null, false, null, false);
  }
  
  /**
   * Go to the beginning of the game.
   **/
  public void goToBeginning () {
    exitScoringMode();
    for (int row = 0; row < size; row++)
      for (int col = 0; col < size; col++) {
	ss.writeStone(row, col, Move.EMPTY);
	groupArray[row][col] = null;
      }
    clearKo();
    capturedBlack = 0;
    capturedWhite = 0;
    setCurrentMove(root);
  }
  
  public void goBackToKibitz () {
    do
      backup(true);
    while (currentMove != root
	   && (currentMove.kibitzes() == null
	       || currentMove.kibitzes().size() == 0));
  }

  /*
   * Permanently undo the previous move.  This only gets called
   * to undo server moves.
   */
  public void undo () {
    Move m = finalServerMove();	// The move to undo
    // Set the move being undone to be a variation.  This will
    // cause it to be moved from the trunk to being a variation
    // the next time a server move is placed.  See placeMove().
    m.setIsVariation(true);
//  m.addKibitz("--undone move--");
    // If undoing the currently displayed move then do a local backup
    // also so the display is updated correctly.  Otherwise don't
    // change the display.
    if (m == currentMove) {
      goBackward(1, false);
      ss.emit();
    }
  }
  
  
  /**
   * Return a vector of all the positions (stones) abutting the given
   * position.
   */
/*
 * Personally, i find this much harder to read than the one below it.  -sigue
 *
  private PositionVector positionsAbutting (Position pos) {
    PositionVector pv = new PositionVector(0, 4);
    int x[] = {-1, 0, 1,  0};
    int y[] = { 0, 1, 0, -1};
    int row = pos.row;
    int col = pos.column;

    for (int i = 0; i < 4; i++) {
      int r = row + y[i];
      int c = col + x[i];
      if (!(r < 0 || r >= size || c < 0 || c >= size)
	  && ss.readStone(r, c) != Move.EMPTY)
	pv.addElement(new Position(r, c));
    }
    return (pv.size() == 0) ? null : pv;
  }
  */

  private PositionVector positionsAbutting (Position pos) {
    PositionVector pv = new PositionVector(0, 4);
    int r = pos.row;
    int c = pos.column;

    if (stoneAt(r + 1, c) != Move.EMPTY)
      pv.addElement(new Position(r + 1, c));
    if (stoneAt(r - 1, c) != Move.EMPTY)
      pv.addElement(new Position(r - 1, c));
    if (stoneAt(r, c + 1) != Move.EMPTY)
      pv.addElement(new Position(r, c + 1));
    if (stoneAt(r, c - 1) != Move.EMPTY)
      pv.addElement(new Position(r, c - 1));
    
    return (pv.size() == 0) ? null : pv;
  }
  
  public SimpleGroupVector groupsAbutting (Move m) {
    SimpleGroupVector groups = null;
    PositionVector placed = m.placedPositions(size);
    if (placed != null) {
      groups = new SimpleGroupVector(1, 2);
      for (int i = 0; i < placed.size(); i++)
	groupsAbutting(placed.elementAt(i), Move.nextColor(m.color()), groups);
    }
    return groups;
  }
  
  /**
   * Return a vector of all the groups abutting the given position
   * that are of the given color.
   **/
  public SimpleGroupVector groupsAbutting (Position pos, int color) {
    return groupsAbutting(pos, color, null);
  }
  
  public SimpleGroupVector groupsAbutting (Position pos, int color,
					   SimpleGroupVector groups) {
    if (groups == null)
      groups = new SimpleGroupVector(1, 2);
    int r = pos.row;
    int c = pos.column;
    SimpleGroup g;
    
    g = groupAt(r - 1, c);
    if (g != null && g.color() == color && groups.indexOf(g) == -1)
      groups.addElement(g);
    
    g = groupAt(r + 1, c);
    if (g != null && g.color() == color && groups.indexOf(g) == -1)
      groups.addElement(g);
    
    g = groupAt(r, c - 1);
    if (g != null && g.color() == color && groups.indexOf(g) == -1)
      groups.addElement(g);
    
    g = groupAt(r, c + 1);
    if (g != null && g.color() == color && groups.indexOf(g) == -1)
      groups.addElement(g);
    
    if (groups.size() == 0)
      return null;
    else
      return groups;
  }
  
  
  /**
   * Update the stoneArray and groupArray to reflect the capture
   * of the given group.
   *
   *   For each stone in the group add a liberty to any groups
   *   abutting that stone.  Update the number of stones captured
   *   for the other player.
   */
  private void captureGroup (SimpleGroup group) {
    int capturingColor = Move.nextColor(group.color());
    synchronized (ss) {
      for (int i = 0; i < group.size(); i++) {
	Position pos = group.positionAt(i);
	ss.writeStone(pos.row, pos.column, Move.EMPTY); // erase stone at pos
	groupArray[pos.row][pos.column] = null; // erase group at pos
	SimpleGroupVector oppGroups = groupsAbutting(pos, capturingColor);
	if (oppGroups != null)
	  for (int j = 0; j < oppGroups.size(); j++) {
	    SimpleGroup oppGroup = oppGroups.elementAt(j);
	    // Note that addLiberty automatically removes duplicates.
	    oppGroup.addLiberty(pos);
	  }
      }
      // Update captured stones, which should always reflect the current
      // state of the game as displayed on the screen.
      if (group.color() == Move.BLACK)
	capturedBlack += group.size();
      else
	capturedWhite += group.size();
    }
  }
  
  /**
   * The mirror image of captureGroup.
   */
  private void uncaptureGroup (SimpleGroup group) {
    if (Debug.debugGameLogicp)
      Debug.println("uncaptureGroup(): " + group);
    int mycolor = group.color();
    int othercolor = Move.nextColor(mycolor);
    synchronized (ss) {
      // Update the stoneArray and the groupArray, removing liberties
      // from abutting groups.
      for (int i = 0; i < group.size(); i++) {
	Position pos = group.positionAt(i);
	ss.writeStone(pos.row, pos.column, mycolor);
	groupArray[pos.row][pos.column] = group;
	SimpleGroupVector oppGroups = groupsAbutting(pos, othercolor);
	if (oppGroups != null)
	  for (int j = 0; j < oppGroups.size(); j++) {
	    SimpleGroup oppGroup = oppGroups.elementAt(j);
	    oppGroup.removeLiberty(pos);
	  }
      }
      
      SimpleGroup newGroup = recomputeGroupAt(group.positionAt(0));
      if (Debug.debugGameLogicp && !group.equals(newGroup)) {
	Debug.println("newGroup = " + newGroup);
      }
      
      // Update captured stones, which should always reflect the current
      // state of the game as displayed on the screen.
      if (mycolor == Move.BLACK)
	capturedBlack -= group.size();
      else
	capturedWhite -= group.size();
    }
  }
  
  /*
   * This is called once a the move is known to be legal.  newGroup
   * is the group that was just created by this move.  It may be a
   * composition of several groups if it was a connecting move.
   */
  // division of labour here between this and StoneMove.update is a bit unclear - 
  // since we are splitting update into legal() and commit(), 
  // suggest this function only fiddle with the Arrays, and be renamed 
  // updateArrays! Shift liberty-swizzling logic also into commit(),
  // and remove third parameter.... AMB at 0.1
  // Now mostly done.... AMB at 0.2
  private void updateArrays (Move m, SimpleGroupVector newGroups,
			     SimpleGroupVector abuttingGroups) {
    synchronized (ss) {
      // Store the new groups in groupArray and stoneArray thus
      // throwing out any groups that used to be at those positions.
      if (newGroups != null)
	for (int i = 0; i < newGroups.size(); i++) {
	  SimpleGroup group = newGroups.elementAt(i);
	  int color = group.color();
	  for (int j = 0; j < group.size(); j++) {
	    Position pos = group.positionAt(j);
	    groupArray[pos.row][pos.column] = group;
	    ss.writeStone(pos.row, pos.column, color);
	  }
	}
      
      // Remove any captured groups from both the group array and stone array.
      if (m.capturedGroups() != null)
	for (int j = 0; j < m.capturedGroups().size(); j++)
	  captureGroup(m.capturedGroups().elementAt(j));
      
      // Remove liberties from the groups abutting the newly placed stone(s).
      if (abuttingGroups != null) {
	for (int k = 0; k < abuttingGroups.size(); k++) {
	  SimpleGroup group = abuttingGroups.elementAt(k);
	  for (int l = 0; l < m.placedPositions(size).size(); l++) {
	    Position lib = m.placedPositions(size).elementAt(l);
	    group.removeLiberty(lib);
	  }
	}
      }
    }
  }
  
  /**
   * Create a new group from a set of groups that are being connected
   * by the placement of the given position.  If newGroup is non-null
   * then store the new group in it (as a kludge to get around lack 
   * of multiple value returns).
   **/
  public SimpleGroup composeGroups (SimpleGroupVector groups, int color,
				    Position pos) {
    SimpleGroup newGroup = new SimpleGroup(color);
    
    if (groups != null) {
      // add the positions of each of the old groups to the new group.
      for (int i = 0; i < groups.size(); i++) {
	SimpleGroup group = groups.elementAt(i);
	for (int j = 0; j < group.size(); j++)
	  newGroup.addPosition(group.positionAt(j));
      }
      // update the liberties of the new group.  the new liberties
      // are the union of the liberties of the groups and the new
      // position.  The union is automatically taken because addLiberty()
      // will only add a liberty if it isn't already present.
      for (int i = 0; i < groups.size(); i++) {
	SimpleGroup group = groups.elementAt(i);
	for (int j = 0; j < group.numberOfLiberties(); j++)
	  newGroup.addLiberty(group.libertyAt(j));
      }
    }
    // Add the connecting position to the new group.
    // This automatically removes pos as a liberty.
    newGroup.addPosition(pos);
    
    PositionVector poslibs = getLiberties(pos);
    for (int i = 0; i < poslibs.size(); i++)
      newGroup.addLiberty(poslibs.elementAt(i));
    return newGroup;
  }
  
  
  
  public PositionVector getLiberties (Position pos) {
    PositionVector positions = new PositionVector(2, 4);
    int r = pos.row;
    int c = pos.column;
    int size = this.size - 1;
    
    if (r > 0 && ss.readStone(r - 1, c) == Move.EMPTY)
      positions.addElement(new Position(r - 1, c));
    
    if (r < size && ss.readStone(r + 1, c) == Move.EMPTY)
      positions.addElement(new Position(r + 1, c));
    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -