Example #1
0
// checkHandicapBrds checks the LowStates of the Nodes
// only suitable for special set boards
func checkHandicapBrds(brd1, brd2 *ah.AbstHier) (ret bool) {
	var c ah.ColValue
	var r ah.RowValue
	nCol, nRow := brd1.GetSize()
	nCol2, nRow2 := brd2.GetSize()
	if (nCol != nCol2) || (nRow != nRow2) {
		ret = true
	} else {
		for r = 0; ah.RowSize(r) < nRow; r++ {
			for c = 0; ah.ColSize(c) < nCol; c++ {
				nl := ah.MakeNodeLoc(c, r)
				bp1 := &brd1.Graphs[ah.PointLevel].Nodes[nl]
				bp2 := &brd2.Graphs[ah.PointLevel].Nodes[nl]
				low1 := bp1.GetNodeLowState()
				low2 := bp2.GetNodeLowState()
				// check that both are occupied or unoccupied
				if ah.IsOccupied(ah.PointStatus(low1)) != ah.IsOccupied(ah.PointStatus(low2)) {
					ret = true
					break
				}
			}
		}
	}
	return ret
}
Example #2
0
// Print the boards, after transformation
func printBrds(msg string, brd *ah.AbstHier, newBrd *ah.AbstHier, tName string) {
	var c ah.ColValue
	var r ah.RowValue
	nCol, nRow := brd.GetSize()
	fmt.Println("Board size", int(nCol), "by", int(nRow), "after", tName)
	for r = 0; ah.RowSize(r) < nRow; r++ {
		for c = 0; ah.ColSize(c) < nCol; c++ {
			bp := brd.Graphs[ah.PointLevel].GetPoint(c, r)
			ch := bp.GetNodeLowState()
			fmt.Printf("%c", byte(ch))
		}
		fmt.Print(" | ")
		for c = 0; ah.ColSize(c) < nCol; c++ {
			nbp := newBrd.Graphs[ah.PointLevel].GetPoint(c, r)
			ch := nbp.GetNodeLowState()
			fmt.Printf("%c", byte(ch))
		}
		fmt.Println()
	}
}
Example #3
0
// differBrds checks the LowStates of the Nodes
// only suitable for special set boards
func differBrds(brd1, brd2 *ah.AbstHier) (ret bool) {
	var c ah.ColValue
	var r ah.RowValue
	nCol, nRow := brd1.GetSize()
	nCol2, nRow2 := brd2.GetSize()
	if (nCol != nCol2) || (nRow != nRow2) {
		ret = true
	} else {
		for r = 0; ah.RowSize(r) < nRow; r++ {
			for c = 0; ah.ColSize(c) < nCol; c++ {
				nl := ah.MakeNodeLoc(c, r)
				bp1 := &brd1.Graphs[ah.PointLevel].Nodes[nl]
				bp2 := &brd2.Graphs[ah.PointLevel].Nodes[nl]
				if bp1.GetNodeLowState() != bp2.GetNodeLowState() {
					ret = true
					break
				}
			}
		}
	}
	return ret
}
Example #4
0
// printInitBoard prints the PointType values
// after a Board is initialized (via SetSize)
func printInitBoard(abhr *ah.AbstHier, title string) {

	//	Black_Occ_Pt:		"◉",
	//	White_Occ_Pt:		"◎",

	var c ah.ColValue
	var r ah.RowValue
	nCol, nRow := abhr.GetSize()
	fmt.Println(title, "Board", int(nCol), "by", int(nRow))
	for r = 0; ah.RowSize(r) < nRow; r++ {
		for c = 0; ah.ColSize(c) < nCol; c++ {
			bp := abhr.Graphs[ah.PointLevel].GetPoint(c, r)
			hs := bp.GetNodeHighState()
			if hs == uint16(ah.White) {
				fmt.Print("◎")
			} else if hs == uint16(ah.Black) {
				fmt.Print("◉")
			} else {
				fmt.Print(ah.PtTypeNames[bp.GetPointType()])
			}
		}
		fmt.Println()
	}
}
Example #5
0
File: parser.go Project: Ken1JF/sgf
func (p *Parser) processProperty(pv PropertyValue, nodd TreeNodeIdx) (ret TreeNodeIdx) {
	if p.trace {
		defer un(trace(p, "processProperty"))
	}
	ret = nodd
	// TODO: get rid of idx when all the "Not implemented:" messages are gone...
	idx := pv.PropType
	//	fmt.Println("Node", nodd, "idx", idx, "Description", GetProperty(idx).Description);
	//	os.Exit(998)
	if p.dbstat {
		if idx >= 0 {
			p.DBStats.ID_Counts[idx] += 1
		} else {
			p.DBStats.Unkn_Count += 1
		}
	}
	switch idx {

	case AB_idx:
		if pv.ValType == Point {
			// Add point to Board
			mov, err := SGFPoint(pv.StrValue)
			if len(err) != 0 {
				p.errors.Add(p.pos, "Bad Point for AB: "+err.Error()+" B["+string(pv.StrValue)+"]")
			} else {
				err = p.DoAB(mov, p.play)
				if len(err) != 0 {
					p.errors.Add(p.pos, "Error from DoAB: "+err.Error()+" B["+string(pv.StrValue)+"]")
				}
			}
			// Record the property:
			p.addProp(ret, pv)
		} else {
			str := pv.StrValue
			for len(str) > 0 { // compressed list of Points
				// Make a new pv
				npv := pv
				npv.StrValue = str[0:2]
				// Add point to Board
				mov, err := SGFPoint(npv.StrValue)
				if len(err) != 0 {
					p.errors.Add(p.pos, "Bad Point List element for AB: "+err.Error()+" B["+string(pv.StrValue)+"]")
				} else {
					err = p.DoAB(mov, p.play)
					if len(err) != 0 {
						p.errors.Add(p.pos, "Error from DoAB:"+err.Error()+"in List element, B["+string(pv.StrValue)+"]")
					}
				}
				str = str[2:]
			}
			// Record the property: (only once)
			p.addProp(ret, pv)
		}

	case AE_idx:
		if pv.ValType == Point {
			// Add point to Board
			mov, err := SGFPoint(pv.StrValue)
			if len(err) != 0 {
				p.errors.Add(p.pos, "Bad Point for AE: "+err.Error()+": from "+string(pv.StrValue))
			} else {
				err = p.DoAE(mov, p.play)
				if len(err) != 0 {
					p.errors.Add(p.pos, "Error from DoAE: "+err.Error()+": caused by "+string(pv.StrValue))
				}
			}
			// Record the property:
			p.addProp(ret, pv)
		} else {
			str := pv.StrValue
			for len(str) > 0 { // compressed list of Points
				// Make a new pv
				npv := pv
				npv.StrValue = str[0:2]
				// Add point to Board
				mov, err := SGFPoint(npv.StrValue)
				if len(err) != 0 {
					p.errors.Add(p.pos, "Bad Point List element for AE: "+err.Error()+": from "+string(npv.StrValue))
				} else {
					err = p.DoAE(mov, p.play)
					if len(err) != 0 {
						p.errors.Add(p.pos, "Error from DoAE:"+err.Error()+" in List element: "+string(npv.StrValue))
					}
				}
				str = str[2:]
			}
			// Record the property: (only once)
			p.addProp(ret, pv)
		}

	case AN_idx:
		// set the board AN:
		p.SetAN(pv.StrValue)
		// Record the property:
		p.addProp(ret, pv)

	case AP_idx:
		// set the board AP:
		p.SetAP(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case AR_idx:
		// set the board AR:
		p.DoAR(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case AS_idx:
		// record the property:
		p.addProp(ret, pv)

	case AW_idx:
		if pv.ValType == Point {
			// Add point to Board
			mov, err := SGFPoint(pv.StrValue)
			if len(err) != 0 {
				p.errors.Add(p.pos, "Bad Point for AW: "+err.Error()+": from "+string(pv.StrValue))
			} else {
				err = p.DoAW(mov, p.play)
				if len(err) != 0 {
					p.errors.Add(p.pos, "Error from DoAW: "+err.Error()+": caused by "+string(pv.StrValue))
				}
			}
			// Record the property:
			p.addProp(ret, pv)
		} else {
			str := pv.StrValue
			for len(str) > 0 { // compressed list of Points
				// Make a new pv
				npv := pv
				npv.StrValue = str[0:2]
				// Add point to Board
				mov, err := SGFPoint(npv.StrValue)
				if len(err) != 0 {
					p.errors.Add(p.pos, "Bad Point List element for AW: "+err.Error()+": from "+string(npv.StrValue))
				} else {
					err = p.DoAW(mov, p.play)
					if len(err) != 0 {
						p.errors.Add(p.pos, "Error from DoAW: "+err.Error()+" in List element: "+string(npv.StrValue))
					}
				}
				str = str[2:]
			}
			// Record the property: (once)
			p.addProp(ret, pv)
		}

	case B_idx:
		p.treeNodes[ret].TNodType = BlackMoveNode
		mov, err := SGFPoint(pv.StrValue)
		if len(err) != 0 {
			p.errors.Add(p.pos, err.Error()+" in SGFPoint, B["+string(pv.StrValue)+"]")
		} else {
			p.treeNodes[ret].propListOrNodeLoc = PropIdx(mov)
			movN, err := p.DoB(mov, p.play)
			if movN == 1 && p.dbstat {
				p.SetPlayerRank()
			}
			if len(err) != 0 {
				p.warnings.Add(p.pos, err.Error()+" B["+string(pv.StrValue)+"]")
			}
			if (p.moveLimit > 0) && (movN >= p.moveLimit) {
				p.limitReached = true
				if p.trace {
					p.printTrace("limitReached set to true in B")

				}
			}
		}

	case BL_idx:
		// record the property:
		p.addProp(ret, pv)

	case BM_idx:
		// record the property:
		p.addProp(ret, pv)

	case BR_idx:
		// set the board BR:
		p.SetBR(pv.StrValue)
		if p.dbstat {
			// count the BR values:
			idx := string(pv.StrValue)
			n, _ := p.DBStats.BWRank_map[idx]
			p.DBStats.BWRank_map[idx] = n + 1
			// check the rank
			errStr := check_Rank(pv.StrValue)
			if errStr != "" {
				p.ReportException(BR_idx, pv.StrValue, errStr)
			}
		}
		// record the property:
		p.addProp(ret, pv)

	case BT_idx:
		// set the board BT:
		p.SetBT(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case C_idx:
		// record the property:
		// TODO: need to process escape characters?
		if (p.mode & ParseComments) != 0 {
			p.addProp(ret, pv)
		}

	case CA_idx:
		// TODO: implement support for different char sets
		// record the property:
		p.addProp(ret, pv)

	case CP_idx:
		// record the property:
		p.addProp(ret, pv)

	case CR_idx:
		// record the property:
		p.addProp(ret, pv)

	case DD_idx:
		// record the property:
		p.addProp(ret, pv)

	case DM_idx:
		// record the property:
		p.addProp(ret, pv)

	case DO_idx:
		// record the property:
		p.addProp(ret, pv)

	case DT_idx:
		// set the board DT:
		p.SetDT(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case EV_idx:
		// set the board EV:
		p.SetEV(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case FF_idx:
		// set the board FF:
		p.SetFF(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case FG_idx:
		// record the property:
		p.addProp(ret, pv)

	case GB_idx:
		// record the property:
		p.addProp(ret, pv)

	case GC_idx:
		// set the board GC:
		p.SetGC(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case GM_idx:
		// Check the GM:
		i, _ := strconv.Atoi(string(pv.StrValue))
		if i != 1 {
			p.errors.Add(p.pos, "GM not 1: "+string(pv.StrValue))
		}
		// record the property:
		p.addProp(ret, pv)

	case GN_idx:
		// record the property:
		p.addProp(ret, pv)

	case GW_idx:
		// record the property:
		p.addProp(ret, pv)

	case HA_idx:
		// count the HA values:
		idx := string(pv.StrValue)
		if p.dbstat {
			n, _ := p.DBStats.HA_map[idx]
			p.DBStats.HA_map[idx] = n + 1
		}
		// set the board HA:
		i, err := strconv.Atoi(idx)
		if err != nil {
			p.ReportException(HA_idx, pv.StrValue, err.Error())
		}
		p.SetHA(i)
		// record the property:
		p.addProp(ret, pv)

	case HO_idx:
		// record the property:
		p.addProp(ret, pv)

	case IP_idx:
		// record the property:
		p.addProp(ret, pv)

	case IT_idx:
		// record the property:
		p.addProp(ret, pv)

	case IY_idx:
		// record the property:
		p.addProp(ret, pv)

	case KM_idx:
		// set the board KM:
		f, err := strconv.ParseFloat(string(pv.StrValue), 64)
		if err == nil {
			p.SetKM(float32(f), true)
		} else {
			if (len(pv.StrValue) == 1) && (pv.StrValue[0] == '?') {
				p.SetKM(0.0, false)
			} else {
				p.ReportException(KM_idx, pv.StrValue, err.Error())
			}
		}
		// record the property
		p.addProp(ret, pv)

	case KO_idx:
		// TODO: process?
		// record the property:
		p.addProp(ret, pv)

	case LB_idx:
		// record the property:
		p.addProp(ret, pv)

	case LN_idx:
		// set the board LN:
		p.DoLN(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case MA_idx:
		// record the property:
		p.addProp(ret, pv)

	case MN_idx:
		// record the property:
		p.addProp(ret, pv)

	case N_idx:
		// record the property
		// TODO: allow lookup of nodes by name?
		p.addProp(ret, pv)

	case OB_idx:
		// record the property:
		p.addProp(ret, pv)

	case OH_idx:
		// count the OH values:
		strVal := fix_OH(pv.StrValue)
		//use this to validate OH values:
		errStr := check_OH(strVal)
		if errStr != "" {
			p.ReportException(OH_idx, pv.StrValue, errStr)
		}
		idx := string(strVal)
		if p.dbstat {
			n, _ := p.DBStats.OH_map[idx]
			p.DBStats.OH_map[idx] = n + 1
		}
		// set the board OH:
		p.SetOH(strVal)
		// record the property:
		p.addProp(ret, pv)

	case ON_idx:
		// record the property:
		p.addProp(ret, pv)

	case OT_idx:
		// record the property:
		p.addProp(ret, pv)

	case OW_idx:
		// record the property:
		p.addProp(ret, pv)

	case PB_idx:
		// set the board PB:
		p.SetPB(pv.StrValue)
		if p.dbstat {
			// count the Player values:
			idx := string(pv.StrValue)
			n, _ := p.DBStats.BWPlayer_map[idx]
			n.NGames += 1
			if n.FirstGame == "" {
				n.FirstGame = GameName(p.pos.Filename)
				p.GameTree.setFirstBRank = true
			}
			n.LastGame = GameName(p.pos.Filename)
			p.DBStats.BWPlayer_map[idx] = n
			// check the name
			errStr := check_Name(pv.StrValue)
			if errStr != "" {
				p.ReportException(PB_idx, []byte(""), errStr)
			}
		}
		// record the property:
		p.addProp(ret, pv)

	case PC_idx:
		// set the board PC:
		p.SetPC(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case PL_idx:
		// record the property:
		p.addProp(ret, pv)

	case PM_idx:
		// record the property:
		p.addProp(ret, pv)

	case PW_idx:
		// set the board PW:
		p.SetPW(pv.StrValue)
		if p.dbstat {
			// count the Player values:
			idx := string(pv.StrValue)
			n, _ := p.DBStats.BWPlayer_map[idx]
			n.NGames += 1
			if n.FirstGame == "" {
				n.FirstGame = GameName(p.pos.Filename)
				p.GameTree.setFirstWRank = true
			}
			n.LastGame = GameName(p.pos.Filename)
			p.DBStats.BWPlayer_map[idx] = n
			// check the name
			errStr := check_Name(pv.StrValue)
			if errStr != "" {
				p.ReportException(PW_idx, []byte(""), errStr)
			}
		}
		// record the property:
		p.addProp(ret, pv)

	case RE_idx:
		// separate RE and RC (Result Comment)
		RE_val, RE_com := SplitRE(pv.StrValue)
		if p.dbstat {
			// count the RE values:
			idx := string(RE_val)
			n, _ := p.DBStats.RE_map[idx]
			p.DBStats.RE_map[idx] = n + 1
			errStr := check_RE(RE_val)
			if errStr != "" {
				p.ReportException(RE_idx, RE_val, errStr)
			}
		}
		// count the RE comments:
		RE_bas, n, ch, both := TakeOutNum(RE_com)
		if p.dbstat {
			if len(RE_bas) > 0 {
				idx2 := string(RE_bas)
				n, _ := p.DBStats.RC_map[idx2]
				p.DBStats.RC_map[idx2] = n + 1
			}
		}
		// set the board RE:
		p.SetRE(RE_val, RE_bas, n, ch, both)
		// record the property:
		p.addProp(ret, pv)

	case RO_idx:
		// set the board RO:
		p.SetRO(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case RU_idx:
		// count the RU values:
		idx := string(pv.StrValue)
		if p.dbstat {
			n, _ := p.DBStats.RU_map[idx]
			p.DBStats.RU_map[idx] = n + 1
		}
		// set the board RU:
		p.SetRU(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case S_idx: // Represent a S property as 1 node with Black move + property list of other moves:
		p.treeNodes[ret].TNodType = SequenceNode
		mov, err := SGFPoint(pv.StrValue)
		p.treeNodes[ret].propListOrNodeLoc = PropIdx(mov)
		if len(err) != 0 {
			p.errors.Add(p.pos, err.Error()+": from "+string(pv.StrValue))
		}
		movColor := ah.Black
		for len(pv.StrValue) > 2 {
			pv.StrValue = pv.StrValue[2:]
			movColor = ah.OppositeColor(movColor)
			ret = p.addNode(ret, SequenceNode)
			mov, err = SGFPoint(pv.StrValue)
			p.treeNodes[ret].propListOrNodeLoc = PropIdx(mov)
			if len(err) != 0 {
				p.errors.Add(p.pos, err.Error()+": from "+string(pv.StrValue))
			}
		}
		// record the property:
		// TODO: figure out how to undo the expansion: (need a test or 2)
		//			p.addProp(ret, pv)	// don't record, got expanded into a sequence of Nodes...

	case SE_idx:
		// record the property:
		p.addProp(ret, pv)

	case SL_idx:
		// record the property:
		p.addProp(ret, pv)

	case SO_idx:
		// set the board SO:
		p.SetSO(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case SQ_idx:
		// record the property:
		p.addProp(ret, pv)

	case ST_idx:
		// set the board ST:
		p.SetST(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case SU_idx:
		// record the property:
		p.addProp(ret, pv)

	case SZ_idx:
		// set the board size:
		var col int
		var row int
		idx_colon := strings.Index(string(pv.StrValue), ":")
		if idx_colon > 0 {
			col, _ = strconv.Atoi(string(pv.StrValue[0:idx_colon]))
			row, _ = strconv.Atoi(string(pv.StrValue[idx_colon+1:]))
		} else {
			col, _ = strconv.Atoi(string(pv.StrValue))
			row = col
		}
		p.InitAbstHier(ah.ColSize(col), ah.RowSize(row), ah.StringLevel, p.play) // TODO: vary this?
		// record the property:
		p.addProp(ret, pv)

	case TB_idx:
		// record the property:
		p.addProp(ret, pv)

	case TE_idx:
		// record the property:
		p.addProp(ret, pv)

	case TM_idx:
		// set the board TM:
		// see if it is a real (float32) value (in seconds)
		f, err := strconv.ParseFloat(string(pv.StrValue), 32)
		if err != nil {
			str := pv.StrValue
			// see if it is hours:
			idx := bytes.IndexByte(str, 'h')
			if idx > 0 {
				h, err2 := strconv.ParseFloat(string(str[0:idx]), 32)
				if err2 == nil {
					f = 60 * 60 * h
					if idx < len(str)-1 {
						str = str[idx+1:]
						for (len(str) > 0) && (str[0] == ' ') {
							str = str[1:]
						}
						if len(str) > 0 {
							idx = bytes.IndexByte(str, 'm')
							if idx > 0 {
								m, err3 := strconv.ParseFloat(string(str[0:idx]), 32)
								if err3 == nil {
									f += 60 * m
									if idx < len(str)-1 {
										p.ReportException(TM_idx, pv.StrValue, "Extra h+m value: "+string(str[idx+1:]))
										//											p.errors.Add(p.pos, "Extra h+m value: " + str[idx+1 :] + ": from " + string(pv.StrValue))
									}
								} else {
									p.ReportException(TM_idx, pv.StrValue, err3.Error())
									//										p.errors.Add(p.pos, "Bad minute value: " + err3.Error() + ": from " + string(pv.StrValue))
								}
							} else {
								idx = bytes.Index(str, []byte("sudden death"))
								if idx < 0 {
									idx = bytes.Index(str, []byte("each"))
									if idx < 0 {
										p.ReportException(TM_idx, pv.StrValue, "Extra h value: "+string(str))
										//											p.errors.Add(p.pos, "Extra h value: " + str +  ": from " + string(pv.StrValue))
									}
								}
							}
						}
					}
				} else {
					p.ReportException(TM_idx, pv.StrValue, err2.Error())
					//						p.errors.Add(p.pos, "Bad hour value: " + err2.Error() + ": from " + string(pv.StrValue[0:idx]))
				}
			} else {
				idx := bytes.IndexByte(str, 'm')
				if idx > 0 {
					m, err3 := strconv.ParseFloat(string(str[0:idx]), 32)
					if err3 == nil {
						f = 60 * m
						if idx < len(str)-1 {
							str = str[idx+1:]
							for (len(str) > 0) && (str[0] == ' ') {
								str = str[1:]
							}
							if len(str) > 0 {
								idx = bytes.IndexByte(str, 's')
								if idx > 0 {
									s, err4 := strconv.ParseFloat(string(str[0:idx]), 32)
									if err4 == nil {
										f += s
										if idx < len(str)-1 {
											p.ReportException(TM_idx, pv.StrValue, "Extra m+s value: "+string(str[idx+1:]))
											//												p.errors.Add(p.pos, "Extra m+s value: " + str[idx+1 :] + ": from " + string(pv.StrValue))
										}
									} else {
										p.ReportException(TM_idx, pv.StrValue, "Extra m+s value: "+string(str[idx+1:]))
										//											p.errors.Add(p.pos, "Bad second value: " + err4.String() + ": from " + string(pv.StrValue))
									}
								} else {
									idx = bytes.Index(str, []byte("sudden death"))
									if idx < 0 {
										p.ReportException(TM_idx, pv.StrValue, "Extra m value: "+string(str))
										//											p.errors.Add(p.pos, "Extra m value: " + str + ": from " + string(pv.StrValue))
									}
								}
							}

						}
					} else {
						p.ReportException(TM_idx, pv.StrValue, err3.Error()+"Bad minute value: "+string(str))
						//							p.errors.Add(p.pos, "Bad minute value: " + err3.String() + ": from " + string(pv.StrValue))
					}
				} else {
					p.ReportException(TM_idx, pv.StrValue, err.Error())
					//						p.errors.Add(p.pos, "Bad Timelimit value: " + err.Error() + ": from " + str)
				}
			}
		}
		p.SetTM(float32(f))
		// record the property
		p.addProp(ret, pv)

	case TR_idx:
		// record the property:
		p.addProp(ret, pv)

	case TW_idx:
		// record the property:
		p.addProp(ret, pv)

	case UC_idx:
		// record the property:
		p.addProp(ret, pv)

	case US_idx:
		// set the board US:
		p.SetUS(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case V_idx:
		// record the property:
		p.addProp(ret, pv)

	case VW_idx:
		// record the property:
		p.addProp(ret, pv)

	case W_idx:
		p.treeNodes[ret].TNodType = WhiteMoveNode
		mov, err := SGFPoint(pv.StrValue)
		if len(err) != 0 {
			p.errors.Add(p.pos, err.Error()+" in SGFPoint, W["+string(pv.StrValue)+"]")
		} else {
			p.treeNodes[ret].propListOrNodeLoc = PropIdx(mov)
			movN, err := p.DoW(mov, p.play)
			if len(err) != 0 {
				p.warnings.Add(p.pos, err.Error()+" W["+string(pv.StrValue)+"]")
			}
			if movN == 1 && p.dbstat {
				p.SetPlayerRank()
			}
			if (p.moveLimit > 0) && (movN >= p.moveLimit) {
				p.limitReached = true
				if p.trace {
					p.printTrace("limitReached set to true in W")

				}
			}
		}

	case WB_idx:
		// record the property:
		p.addProp(ret, pv)

	case WC_idx:
		// record the property:
		p.addProp(ret, pv)

	case WL_idx:
		// record the property:
		p.addProp(ret, pv)

	case WO_idx:
		// record the property:
		p.addProp(ret, pv)

	case WR_idx:
		// set the board WR:
		p.SetWR(pv.StrValue)
		if p.dbstat {
			// count the WR values:
			idx := string(pv.StrValue)
			n, _ := p.DBStats.BWRank_map[idx]
			p.DBStats.BWRank_map[idx] = n + 1
			// check the rank
			errStr := check_Rank(pv.StrValue)
			if errStr != "" {
				p.ReportException(WR_idx, pv.StrValue, errStr)
			}
		}
		// record the property:
		p.addProp(ret, pv)

	case WT_idx:
		// set the board WT:
		p.SetWT(pv.StrValue)
		// record the property:
		p.addProp(ret, pv)

	case WW_idx:
		// record the property:
		p.addProp(ret, pv)

	case UnknownPropIdx:
		// for UnknownProperty, add composed two strings: first is name, second is value
		str := string(p.UnknownProperty.ID) + ":" + string(pv.StrValue)
		pv.StrValue = []byte(str)
		p.addProp(ret, pv)
		if (p.mode & ParserIgnoreUnknSGF) == 0 {
			p.warnings.Add(p.pos, "Unknown SGF property: "+str)
		}

	default:
		p.errors.Add(p.pos, "Not Implemented: "+"default:")
	}
	return ret
}