// 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 }
// 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() } }
// 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 }
// 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() } }
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 }