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

📄 move.java

📁 ErGo是一个很早的Java通用围棋服务器(IGS/NNGS)客户端程序。有全部源码和文档
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package ergo.logic;

// $Id: Move.java,v 1.2 1999/08/13 01:17:49 sigue Exp $

import ergo.util.*;
import java.util.Vector;
import java.io.PrintWriter;

/**
  * Move represents a Go move and at the same time represents a game tree
  * consisting of this move and all moves below it.  I might want to
  * separate out that functionality into a GameTree class but this seemed
  * to provide better access to the tree since most of the time it's a move
  * that is passed around.  Move is the base class for the various types
  * of moves such as StoneMove, HandicapMove, and PassMove.
  *
  * For server games there is a distinction between "trunk" moves and
  * "variations", with the intuitive meanings.  The trunk, or actual
  * game, is stored in the successive "child" fields of each move.  If
  * there is no trunk child move for a given move then the child may
  * contain a variation; a non-trunk move.  If it does contain a
  * variation, then when a trunk move arrives it occupies the child
  * slot and the variation is moved into the variations vector.  This
  * makes browsing simpler since it means that if the child is null
  * then there are no variations either. [later] It also means a bunch
  * of other things are harder, so I'm not sure it was a good choice.
  * [even later] This is a mess.
  *
  * +++ The class hierarchy is broken:  HandicapMove should be a subclass
  * of StoneMove.
  *
  * +++ Since there can be hundreds of moves to a game, we may want to
  * combine several of the fields that hold small integers or booleans
  * into one integer field and extract the subfields via bit-swizzling.
  */

public abstract class Move {
  // These constants are chosen to correspond with the 
  public static final int BLACK = 0;
  public static final int WHITE = 1;
  public static final int EMPTY = 3;
  public static final int WHITETERRITORY = 4;
  public static final int BLACKTERRITORY = 5;
  public static final int SEEN = 6;	// for scoring only
  public static final int NONE = 7;	// for scoring only
  public static final int BLACKSHADOW = 10;
  public static final int WHITESHADOW = 11;
  public static final int BOTH = 12; // never stored in board array

  protected Move parent;	// The previous move.
  protected Move child; // The next trunk move (or variation, if no trunk).
  protected int color;

  // I've already forgotten for sure, but I think the deal is that
  // a move is a variation if it's NOT a server move.
  protected boolean isVariation; // true if variation, false if trunk move.

  // Vector of kibitzes that were made BEFORE this move was played
  // and after the previous move.
  protected Vector kibitzes;

  // The variations field is a vector of moves, which represent
  // branches in the game tree.
  protected Vector variations;

  // Time left (in seconds) after this move was played.  This is unused
  // if playing local-only moves.
  protected int timeLeft = -1;

  // The move number is the move number that the server assigns to this
  // move, or, if this is a local move the move number will be assigned 
  // sequentially starting at the number of the previous branch in the
  // move tree.
  protected int moveNumber;

  // A move has been committed if Move.commit() has been called.
  // It's necessary to have this field in order to know whether
  // or not captured groups have been calculated for this move, etc.
  protected boolean isCommitted = false;

  // A vector of SGF properties and their values that should be saved
  // when this move is saved.  This is normally null unless the game
  // was loaded from a file, in which case unhandled properties
  // corresponding to this move are stored here.
  protected Vector unhandledSGFproperties = null;

  Move () { }
  
  Move (Move parent, int timeleft, int number, int color, boolean isVar) {
    this.parent = parent;

    if ((parent == null && color != WHITE) // is root white?
	|| (parent != null && color != parent.nextColor()))
      Debug.println("Incorrect color for move #" + number);
    if (parent != null && number != parent.moveNumber() + 1)
      Debug.println("Move numbers not in sequence: " + number);

    // The root is not displayed.  If we set its color to white
    // the first displayed move will be black.
    this.color = (parent == null) ? WHITE : parent.nextColor();
/*
    if (parent == null && number != 0)
      throw new GoMoveOutOfOrder(number);
    else if (parent != null && number != (parent.moveNumber() + 1))
      throw new GoMoveOutOfOrder(number, parent.moveNumber());
*/
    this.timeLeft = timeleft;
    moveNumber = number;
    isVariation = isVar;
  }

  public int moveNumber () { return moveNumber; }

  public Move child () { return child; }

  public void setChild (Move hija) { child = hija; }

  public Move parent () { return parent; }

  public int color () { return color; }

  public Vector kibitzes () { return kibitzes; }

  public boolean hasKibitzes () {
    return (kibitzes != null && kibitzes.size() > 0);
  }

  public SimpleGroupVector newGroups (Game g) { return null; }

  public boolean isCommitted () { return isCommitted; }

  public void commit () {
    isCommitted = true;
    link();
  }

  public void addSGFproperty (String property, Vector values) {
    //Debug.println("Adding prop " + property + " to move " + this);
    //for (int i = 0; i < values.size(); i++)
    //  Debug.println("val " + i + " = " + values.elementAt(i));
    if (unhandledSGFproperties == null)
      unhandledSGFproperties = new Vector(2, 4);
    Vector pair = new Vector(2);
    pair.addElement(property);
    pair.addElement(values);
    unhandledSGFproperties.addElement(pair);
  }

  // Make this move a permanent part of the game tree.  This is done
  // after it has been determined that the move is legal.  (Well, for
  // server moves this is called before we _check_ that it's a legal
  // move, but we _assume_ it's legal if it's from the server.)
  public void link () {
    if (parent == null)
      Debug.println("Error: Attempt to link move with null parent.");
    else if (parent.child() == null)
      parent.setChild(this);	// The simple case.
    else if (this.equals(parent.child())) {
      // +++ I can't remember what this case is for.  Is it a bug???
      // Err, one case where it operates is the case where a server move is
      // received while browsing, and link() is called - then subsequently
      // it is checked (unnecessarily) for legality, which as a byproduct
      // commits it; then it is in fact _actually_ committed , which 
      // subsequently links it (again!) to the tree..... 
      // HTH! Although I suspect this wasn't what you were thinking when you
      // wrote this bit..... AMB
      //
      // This move is functionally equivalent to the old parent.child()
      // so replace the old one but copy its children into the new one
      // so that Game.placeMove() won't get confused about which move
      // is the current move.  "this" will be the current move after
      // linking.
      Move old = parent.child();
      parent.setChild(this);
      child = old.child();
      for (int i = 0; ; i++) {
	if (old.variationAt(i) == null)
	  break;
	else
	  addVariation(old.variationAt(i));
      }
    }
    else if (!isVariation) {
      if (parent.child().isVariation) {
	// Make this move the trunk move since it's not a variation
	// and there is a variation in the trunk move position.
	parent.addVariation(parent.child());
	parent.setChild(this);
      }
      else
	Debug.println("Attempt to link two server moves to the same parent."
		    + "  Not linking move.");
    }
    else
      parent.addVariation(this);
  }


  /*
   * Return the variation at the given index.  An index of -1 means
   * to return the child of this move if the child is a variation.
   */
  public Move variationAt (int var) {
    if (var == -1)
      return child;
    else if (variations == null || variations.size() <= var)
      return null;
    else
      return (Move) variations.elementAt(var);
  }

  /*
   * Return a move that is an immediate child or variation of this
   * move at the given Position, or null.
   */
  public Move variationAt (Position pos) {
    for (int i = -1; variationAt(i) != null; i++) {
      if (variationAt(i).occupiesPosition(pos))
	return variationAt(i);
    }
    return null;
  }


  public boolean isVariation () {
    return isVariation;
  }

  /*
   * Is the given move, m, a variation of this move?
   */
  public boolean isVariation (Move m) {
    if (variations != null)
      for(int i = 0; i < variations.size(); i++)
	if(m == variationAt(i))
	  return true;
    return false;
  }
      

⌨️ 快捷键说明

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