// total_hints = the number of parseble move hints in the gnubg string, ie. 6/off contains one, bar/23 6/3 contains two private Move ParseMoveHint(string move_string, out int count, int total_hints, int[] dice, GameState gamestate) { // from/to // from/to(count) // 'bar'/to // 'bar'/to(count) // from/'off' // from/'off'(count) // from/to*/to* // from/to*/to*/to* // from/'off' // get count and remove it from the string count = 1; int count_start_index = move_string.IndexOf('('); if (count_start_index > 0) { int count_end_index = move_string.IndexOf(')'); count = int.Parse(move_string.Substring(count_start_index + 1, count_end_index - count_start_index - 1)); move_string = move_string.Substring(0, count_start_index); } string[] point_strings = move_string.Split(new char[] { '/' }); List<int> points = new List<int>(); HashSet<int> hitpoints = new HashSet<int>(); bool is_number; foreach (string point_string in point_strings) { bool hit = point_string.Contains("*"); string clean_point_string = point_string; if (hit) clean_point_string = clean_point_string.Replace("*", ""); is_number = true; foreach (char c in clean_point_string) if (!char.IsDigit(c)) { is_number = false; break; } if (is_number) { int point = int.Parse(clean_point_string) - 1; points.Add(point); if (hit) hitpoints.Add(point); } } if (point_strings[0][0] == 'b') points.Insert(0, 24); if (point_strings[point_strings.Length - 1][0] == 'o') points.Insert(points.Count, -1); // points should be sorted from highest to lowest at this point // calculate the missing way points if (dice[0] != dice[1]) { if (count == 1 && points.Count == 2) { int distance = points[0] - points[1]; int bigger_die = Math.Max(dice[0], dice[1]); int smaller_die = Math.Min(dice[0], dice[1]); if (distance > bigger_die)//(points[0] - points[1]) == (dice[0] + dice[1])) { if (distance == (dice[0] + dice[1])) { // Must not contain hits, because gnubg tells about the hit points seperately. if (gamestate.Board.PointCount(gamestate.PlayerOnRoll, points[0] - bigger_die) >= 0) points.Insert(0, (points[0] - bigger_die)); else points.Insert(0, (points[0] - smaller_die)); } else if (points[0] - bigger_die < smaller_die) // bearoff from 6 with 52, need first to do the smaller one. { if (gamestate.Board.PointCount(gamestate.PlayerOnRoll, points[0] - smaller_die) >= 0) // Was broken without this condition on _ _ 8x 2o 2o 2o with dice 43 points.Insert(0, (points[0] - smaller_die)); else if (gamestate.Board.PointCount(gamestate.PlayerOnRoll, points[0] - smaller_die) == -1) points.Insert(0, (points[0] - bigger_die)); else { } } else { throw new InvalidOperationException("Cannot handle this. Help!"); } /*if (gamestate.Board.PointCount(gamestate.PlayerOnRoll, points[0] - bigger_die) > -2) points.Insert(0, (points[0] - bigger_die)); else points.Insert(0, (points[0] - smaller_die));*/ } // This is for lonely bearoffs like |_ _ x _ x x| with 41, gnubg gives one of the hints as '4/off'. // We want atleast 2 chequers on the field because otherwise adding a waypoint is unnecessary inbetween. else if (total_hints == 1 && gamestate.Board.FinishedCount(gamestate.PlayerOnRoll) <= 13 && points[1] == -1 && (points[0] - smaller_die >= 0) && gamestate.Board.PointCount(gamestate.PlayerOnRoll, points[0] - smaller_die) >= 0 && gamestate.Board.LastChequer(gamestate.PlayerOnRoll) <= points[0]) { points.Insert(0, (points[0] - smaller_die)); } else { } } } else { for (int i = 0; i < points.Count - 1; i++) { // This was broken with bearoffs without this condition (ie. 6/off with 44, the below else condition should handle this situation) /*if (points[i + 1] > -1) {*/ int gaps = (points[i] - points[i + 1]) / dice[0]; int mod = (points[i] - points[i + 1]) % dice[0]; if (mod > 0) gaps++; if (gaps > 1) { for (int c = 1; c < gaps; c++) { points.Insert(i + 1, points[i] - dice[0]); i++; } } /*} else { int gaps = (points[i] - points[i + 1]) / dice[0]; int mod = (points[i] - points[i + 1]) % dice[0]; if (mod > 0) { for (int c = 0; c < gaps; c++) { points.Insert(i + 1, points[i] - dice[0]); i++; } } }*/ } } Move move = new Move(); foreach (int point in points) { if (hitpoints.Contains(point)) move.AddHitPoint(point); else move.AddPoint(point); } return move; }
// total_hints = the number of parseble move hints in the gnubg string, ie. 6/off contains one, bar/23 6/3 contains two private Move ParseMoveHint(string move_string, out int count, int total_hints, int[] dice, GameState gamestate) { // from/to // from/to(count) // 'bar'/to // 'bar'/to(count) // from/'off' // from/'off'(count) // from/to*/to* // from/to*/to*/to* // from/'off' // get count and remove it from the string count = 1; int count_start_index = move_string.IndexOf('('); if (count_start_index > 0) { int count_end_index = move_string.IndexOf(')'); count = int.Parse(move_string.Substring(count_start_index + 1, count_end_index - count_start_index - 1)); move_string = move_string.Substring(0, count_start_index); } string[] point_strings = move_string.Split(new char[] { '/' }); List <int> points = new List <int>(); HashSet <int> hitpoints = new HashSet <int>(); bool is_number; foreach (string point_string in point_strings) { bool hit = point_string.Contains("*"); string clean_point_string = point_string; if (hit) { clean_point_string = clean_point_string.Replace("*", ""); } is_number = true; foreach (char c in clean_point_string) { if (!char.IsDigit(c)) { is_number = false; break; } } if (is_number) { int point = int.Parse(clean_point_string) - 1; points.Add(point); if (hit) { hitpoints.Add(point); } } } if (point_strings[0][0] == 'b') { points.Insert(0, 24); } if (point_strings[point_strings.Length - 1][0] == 'o') { points.Insert(points.Count, -1); } // points should be sorted from highest to lowest at this point // calculate the missing way points if (dice[0] != dice[1]) { if (count == 1 && points.Count == 2) { int distance = points[0] - points[1]; int bigger_die = Math.Max(dice[0], dice[1]); int smaller_die = Math.Min(dice[0], dice[1]); if (distance > bigger_die) //(points[0] - points[1]) == (dice[0] + dice[1])) { if (distance == (dice[0] + dice[1])) { // Must not contain hits, because gnubg tells about the hit points seperately. if (gamestate.Board.PointCount(gamestate.PlayerOnRoll, points[0] - bigger_die) >= 0) { points.Insert(0, (points[0] - bigger_die)); } else { points.Insert(0, (points[0] - smaller_die)); } } else if (points[0] - bigger_die < smaller_die) // bearoff from 6 with 52, need first to do the smaller one. { if (gamestate.Board.PointCount(gamestate.PlayerOnRoll, points[0] - smaller_die) >= 0) // Was broken without this condition on _ _ 8x 2o 2o 2o with dice 43 { points.Insert(0, (points[0] - smaller_die)); } else if (gamestate.Board.PointCount(gamestate.PlayerOnRoll, points[0] - smaller_die) == -1) { points.Insert(0, (points[0] - bigger_die)); } else { } } else { throw new InvalidOperationException("Cannot handle this. Help!"); } /*if (gamestate.Board.PointCount(gamestate.PlayerOnRoll, points[0] - bigger_die) > -2) * points.Insert(0, (points[0] - bigger_die)); * else * points.Insert(0, (points[0] - smaller_die));*/ } // This is for lonely bearoffs like |_ _ x _ x x| with 41, gnubg gives one of the hints as '4/off'. // We want atleast 2 chequers on the field because otherwise adding a waypoint is unnecessary inbetween. else if (total_hints == 1 && gamestate.Board.FinishedCount(gamestate.PlayerOnRoll) <= 13 && points[1] == -1 && (points[0] - smaller_die >= 0) && gamestate.Board.PointCount(gamestate.PlayerOnRoll, points[0] - smaller_die) >= 0 && gamestate.Board.LastChequer(gamestate.PlayerOnRoll) <= points[0]) { points.Insert(0, (points[0] - smaller_die)); } else { } } } else { for (int i = 0; i < points.Count - 1; i++) { // This was broken with bearoffs without this condition (ie. 6/off with 44, the below else condition should handle this situation) /*if (points[i + 1] > -1) * {*/ int gaps = (points[i] - points[i + 1]) / dice[0]; int mod = (points[i] - points[i + 1]) % dice[0]; if (mod > 0) { gaps++; } if (gaps > 1) { for (int c = 1; c < gaps; c++) { points.Insert(i + 1, points[i] - dice[0]); i++; } } /*} * else * { * int gaps = (points[i] - points[i + 1]) / dice[0]; * int mod = (points[i] - points[i + 1]) % dice[0]; * if (mod > 0) * { * for (int c = 0; c < gaps; c++) * { * points.Insert(i + 1, points[i] - dice[0]); * i++; * } * } * }*/ } } Move move = new Move(); foreach (int point in points) { if (hitpoints.Contains(point)) { move.AddHitPoint(point); } else { move.AddPoint(point); } } return(move); }