package fr.xtof54.sgfsearch;
import java.io.PrintWriter;
import rene.util.list.ListClass;
import rene.util.list.ListElement;
import rene.util.list.Tree;
import rene.util.xml.XmlWriter;
/**
A node has
<UL>
<LI> a list of actions and a number counter (the number is the number
of the next expected move in the game tree),
<LI> a flag, if the node is in the main game tree,
<LI> a list of changes in this node to be able to undo the node,
<LI> the changes in the prisoner count in this node.
</UL>
@see jagoclient.board.Action
@see jagoclient.board.Change
*/
class Node
{ ListClass Actions; // actions and variations
int N; // next exptected number
boolean Main; // belongs to main variation
ListClass Changes;
public int Pw,Pb; // changes in prisoners in this node
/** initialize with the expected number */
public Node (int n)
{ Actions=new ListClass();
N=n;
Main=false;
Changes=new ListClass();
Pw=Pb=0;
}
/** add an action (at end) */
public void addaction (Action a)
{ Actions.append(new ListElement(a));
}
/** expand an action of the same type as a, else generate a new action */
public void expandaction (Action a)
{ ListElement p=find(a.type());
if (p==null) addaction(a);
else
{ Action pa=(Action)p.content();
pa.addargument(a.argument());
}
}
/**
Expand an action of the same type as a, else generate a new action.
If the action is already present with the same argument, delete
that argument from the action.
*/
public void toggleaction (Action a)
{ ListElement p=find(a.type());
if (p==null) addaction(a);
else
{ Action pa=(Action)p.content();
pa.toggleargument(a.argument());
}
}
/** find the list element containing the action of type s */
ListElement find (String s)
{ ListElement p=Actions.first();
while (p!=null)
{ Action a=(Action)p.content();
if (a.type().equals(s)) return p;
p=p.next();
}
return null;
}
/** find the action and a specified tag */
public boolean contains (String s, String argument)
{ ListElement p=find(s);
if (p==null) return false;
Action a=(Action)p.content();
return a.contains(argument);
}
/** see if the list contains an action of type s */
public boolean contains (String s)
{ return find(s)!=null;
}
/** add an action (at front) */
public void prependaction (Action a)
{ Actions.prepend(new ListElement(a));
}
/**
Insert an action after p.
p <b>must</b> have content type action.
*/
public void insertaction (Action a, ListElement p)
{ Actions.insert(new ListElement(a),p);
}
/** remove an action */
public void removeaction (ListElement la)
{ Actions.remove(la);
}
/**
If there is an action of the type:
Remove it, if arg is "", else set its argument to arg.
Else add a new action in front (if it is true)
*/
public void setaction (String type, String arg, boolean front)
{ ListElement l=Actions.first();
while (l!=null)
{ Action a=(Action)l.content();
if (a.type().equals(type))
{ if (arg.equals(""))
{ Actions.remove(l);
return;
}
else
{ ListElement la=a.arguments();
if (la!=null) la.content(arg);
else a.addargument(arg);
}
return;
}
l=l.next();
}
if (front) prependaction(new Action(type,arg));
else addaction(new Action(type,arg));
}
/** set the action of this type to this argument */
public void setaction (String type, String arg)
{ setaction(type,arg,false);
}
/** get the argument of this action (or "") */
public String getaction (String type)
{ ListElement l=Actions.first();
while (l!=null)
{ Action a=(Action)l.content();
if (a.type().equals(type))
{ ListElement la=a.arguments();
if (la!=null) return (String)la.content();
else return "";
}
l=l.next();
}
return "";
}
/**
Print the node in SGF.
@see jagoclient.board.Action#print
*/
public void print (PrintWriter o)
{ o.print(";");
ListElement p=Actions.first();
Action a;
while (p!=null)
{ a=(Action)p.content();
a.print(o);
p=p.next();
}
o.println("");
}
public void print (XmlWriter xml, int size)
{ int count=0;
Action ra=null,a;
ListElement p=Actions.first();
while (p!=null)
{ a=(Action)p.content();
if (a.isRelevant())
{ count++;
ra=a;
}
p=p.next();
}
if (count==0 && !contains("C"))
{ xml.finishTagNewLine("Node");
return;
}
int number=N-1;
if (count==1)
{ if (ra.type().equals("B") || ra.type().equals("W"))
{ ra.printMove(xml,size,number,this);
number++;
if (contains("C"))
{ a=((Action)find("C").content());
a.print(xml,size,number);
}
return;
}
}
xml.startTagStart("Node");
if (contains("N")) xml.printArg("name",getaction("N"));
if (contains("BL")) xml.printArg("blacktime",getaction("BL"));
if (contains("WL")) xml.printArg("whitetime",getaction("WL"));
xml.startTagEndNewLine();
p=Actions.first();
while (p!=null)
{ a=(Action)p.content();
a.print(xml,size,number);
if (a.type().equals("B") || a.type().equals("W")) number++;
p=p.next();
}
xml.endTagNewLine("Node");
}
/** remove all actions */
public void removeactions ()
{ Actions=new ListClass();
}
/** add a new change to this node */
public void addchange (Change c)
{ Changes.append(new ListElement(c));
}
/** clear the list of changes */
public void clearchanges ()
{ Changes.removeall();
}
// modification methods:
public void main (boolean m) { Main=m; }
/**
Set the Main flag
@param Tree is the tree, which contains this node on root.
*/
public void main (Tree p)
{ Main=false;
try
{ if (((Node)p.content()).main())
{ Main=(this==((Node)p.firstchild().content()));
}
else if (p.parent()==null) Main=true;
}
catch (Exception e) {}
}
public void number (int n) { N=n; }
/**
Copy an action from another node.
*/
public void copyAction (Node n, String action)
{ if (n.contains(action))
{ expandaction(new Action(action,n.getaction(action)));
}
}
// access methods:
public ListElement actions () { return Actions.first(); }
public ListElement lastaction () { return Actions.last(); }
public ListElement changes () { return Changes.first(); }
public ListElement lastchange () { return Changes.last(); }
public int number () { return N; }
public boolean main () { return Main; }
}