public HexagonyEnv(string source, string input, HexagonySettings settings) { if (source.StartsWith("❢")) _linearCode = source.Substring(1); else { _grid = Grid.Parse(source); _ips = Ut.NewArray( new PointAxial(0, -_grid.Size + 1), new PointAxial(_grid.Size - 1, -_grid.Size + 1), new PointAxial(_grid.Size - 1, 0), new PointAxial(0, _grid.Size - 1), new PointAxial(-_grid.Size + 1, _grid.Size - 1), new PointAxial(-_grid.Size + 1, 0)); _ipDirs = Ut.NewArray( Direction.East, Direction.SouthEast, Direction.SouthWest, Direction.West, Direction.NorthWest, Direction.NorthEast); } switch (_inputMode = settings.InputMode) { case InputMode.Utf8: _input = input.ToUtf8(); break; case InputMode.Utf16: _input = input.ToUtf16(); break; case InputMode.Numbers: var m = Regex.Match(input, @"\A(\s*\d+\s*)*\Z", RegexOptions.Singleline); if (!m.Success) throw new InvalidOperationException("The input provided is not a whitespace-separated list of numbers."); _input = m.Groups[1].Captures.Cast<Capture>().Select(c => { byte b; if (!byte.TryParse(c.Value.Trim(), out b)) throw new InvalidOperationException("The number {0} in the input string does not fit in a byte.".Fmt(c.Value.Trim())); return b; }).ToArray(); break; default: throw new InvalidOperationException("Please choose an input mode from the “Input semantics” menu."); } _inputIndex = 0; _settings = settings; if (!settings.MemoryAnnotations.ContainsKey(settings.LastMemoryAnnotationSet)) settings.MemoryAnnotations[settings.LastMemoryAnnotationSet] = new Dictionary<Direction, Dictionary<PointAxial, string>>(); _memory = new Memory(settings.MemoryAnnotations[settings.LastMemoryAnnotationSet]); }
public Bitmap DrawBitmap(HexagonySettings settings, Font defaultValueFont, Font defaultAnnotationFont) { var getX = Ut.Lambda((Direction dir, PointAxial coords) => 4 * coords.Q + 2 * coords.R + (dir is East ? 1 : 0)); var getY = Ut.Lambda((Direction dir, PointAxial coords) => 2 * coords.R + (dir is NorthEast ? 0 : dir is East ? 1 : 2)); int minX = getX(_dir, _mp), maxX = minX; int minY = getY(_dir, _mp), maxY = minY; foreach (var kvp1 in _edges) foreach (var kvp2 in kvp1.Value) { var x = getX(kvp1.Key, kvp2.Key); var y = getY(kvp1.Key, kvp2.Key); minX = Math.Min(minX, x); minY = Math.Min(minY, y); maxX = Math.Max(maxX, x); maxY = Math.Max(maxY, y); } foreach (var kvp1 in _annotations) foreach (var kvp2 in kvp1.Value) { var x = getX(kvp1.Key, kvp2.Key); var y = getY(kvp1.Key, kvp2.Key); minX = Math.Min(minX, x); minY = Math.Min(minY, y); maxX = Math.Max(maxX, x); maxY = Math.Max(maxY, y); } minX -= 3; minY -= 3; maxX += 3; maxY += 3; const int xFactor = 20, yFactor = 34; return GraphicsUtil.DrawBitmap((maxX - minX) * xFactor, (maxY - minY) * yFactor, g => { g.Clear(settings.MemoryBackgroundColor); using (var unusedEdgePen = new Pen(settings.MemoryGridZeroColor)) using (var usedEdgePen = new Pen(settings.MemoryGridNonZeroColor, 2f)) using (var pointerBrush = new SolidBrush(settings.MemoryPointerColor)) using (var valueBrush = new SolidBrush(settings.MemoryValueFont.NullOr(f => f.Color) ?? Color.CornflowerBlue)) using (var annotationBrush = new SolidBrush(settings.MemoryAnnotationFont.NullOr(f => f.Color) ?? Color.ForestGreen)) using (var valueFont = settings.MemoryValueFont.NullOr(f => f.Font)) using (var annotationFont = settings.MemoryAnnotationFont.NullOr(f => f.Font)) { var sfValue = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Near }; var sfAnnotation = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Far }; for (int y = minY; y <= maxY; y++) for (int x = minX; x <= maxX; x++) { if (!((y % 2 == 0 && x % 2 == 0) || ((y % 4 + 4) % 4 == 1 && (x % 4 + 4) % 4 == 1) || ((y % 4 + 4) % 4 == 3 && (x % 4 + 4) % 4 == 3))) continue; var dir = Direction.East; var mp = new PointAxial(0, 0); if (y % 2 != 0) { dir = Direction.East; mp = new PointAxial((x - y) / 4, (y - 1) / 2); } else if ((x - y) % 4 == 0) { dir = Direction.NorthEast; mp = new PointAxial((x - y) / 4, y / 2); } else { dir = Direction.SouthEast; mp = new PointAxial((x - y + 2) / 4, (y - 2) / 2); } var xx = (x - minX) * xFactor; var yy = (y - minY) * yFactor; var hasValue = _edges.ContainsKeys(dir, mp); using (var tr = new GraphicsTransformer(g).Rotate((dir is NorthEast ? -60 : dir is SouthEast ? 60 : 0) + (_cw ? 180 : 0)).Translate(xx, yy)) { g.DrawLine(hasValue ? usedEdgePen : unusedEdgePen, 0, yFactor * -.68f, 0, yFactor * .68f); if (dir == _dir && mp == _mp) g.FillPolygon(pointerBrush, new[] { new PointF(0, yFactor * -.68f), new PointF(3, yFactor * .68f), new PointF(-3, yFactor * .68f) }); } using (var tr = new GraphicsTransformer(g).Rotate((dir is NorthEast ? 30 : dir is SouthEast ? -30 : -90)).Translate(xx, yy)) { if (hasValue) { var str = _edges[dir][mp].ToString(); // Show printable ISO-8859-1 characters if (_edges[dir][mp] >= 0x20 && _edges[dir][mp] <= 0xff && _edges[dir][mp] != 0x7f) try { str += " '" + char.ConvertFromUtf32((int) _edges[dir][mp]) + "'"; } catch { } g.DrawString(str, valueFont ?? defaultValueFont, valueBrush, 0, 0, sfValue); } var annotation = _annotations.Get(dir, mp, null); if (!string.IsNullOrWhiteSpace(annotation)) g.DrawString(annotation, annotationFont ?? defaultAnnotationFont, annotationBrush, 0, 2, sfAnnotation); } } } }); }
public HexagonyEnv(string source, string input, HexagonySettings settings) { if (source.StartsWith("❢")) { _linearCode = source.Substring(1); } else { _grid = Grid.Parse(source); _ips = Ut.NewArray( new PointAxial(0, -_grid.Size + 1), new PointAxial(_grid.Size - 1, -_grid.Size + 1), new PointAxial(_grid.Size - 1, 0), new PointAxial(0, _grid.Size - 1), new PointAxial(-_grid.Size + 1, _grid.Size - 1), new PointAxial(-_grid.Size + 1, 0)); _ipDirs = Ut.NewArray( Direction.East, Direction.SouthEast, Direction.SouthWest, Direction.West, Direction.NorthWest, Direction.NorthEast); } switch (_inputMode = settings.InputMode) { case InputMode.Utf8: _input = input.ToUtf8(); break; case InputMode.Utf16: _input = input.ToUtf16(); break; case InputMode.Numbers: var m = Regex.Match(input, @"\A(\s*\d+\s*)*\Z", RegexOptions.Singleline); if (!m.Success) { throw new InvalidOperationException("The input provided is not a whitespace-separated list of numbers."); } _input = m.Groups[1].Captures.Cast <Capture>().Select(c => { byte b; if (!byte.TryParse(c.Value.Trim(), out b)) { throw new InvalidOperationException("The number {0} in the input string does not fit in a byte.".Fmt(c.Value.Trim())); } return(b); }).ToArray(); break; default: throw new InvalidOperationException("Please choose an input mode from the “Input semantics” menu."); } _inputIndex = 0; _settings = settings; if (!settings.MemoryAnnotations.ContainsKey(settings.LastMemoryAnnotationSet)) { settings.MemoryAnnotations[settings.LastMemoryAnnotationSet] = new Dictionary <Direction, Dictionary <PointAxial, string> >(); } _memory = new Memory(settings.MemoryAnnotations[settings.LastMemoryAnnotationSet]); }
public Bitmap DrawBitmap(HexagonySettings settings, Font defaultValueFont, Font defaultAnnotationFont) { var getX = Ut.Lambda((Direction dir, PointAxial coords) => 4 * coords.Q + 2 * coords.R + (dir is East ? 1 : 0)); var getY = Ut.Lambda((Direction dir, PointAxial coords) => 2 * coords.R + (dir is NorthEast ? 0 : dir is East ? 1 : 2)); int minX = getX(_dir, _mp), maxX = minX; int minY = getY(_dir, _mp), maxY = minY; foreach (var kvp1 in _edges) { foreach (var kvp2 in kvp1.Value) { var x = getX(kvp1.Key, kvp2.Key); var y = getY(kvp1.Key, kvp2.Key); minX = Math.Min(minX, x); minY = Math.Min(minY, y); maxX = Math.Max(maxX, x); maxY = Math.Max(maxY, y); } } foreach (var kvp1 in _annotations) { foreach (var kvp2 in kvp1.Value) { var x = getX(kvp1.Key, kvp2.Key); var y = getY(kvp1.Key, kvp2.Key); minX = Math.Min(minX, x); minY = Math.Min(minY, y); maxX = Math.Max(maxX, x); maxY = Math.Max(maxY, y); } } minX -= 3; minY -= 3; maxX += 3; maxY += 3; const int xFactor = 20, yFactor = 34; return(GraphicsUtil.DrawBitmap((maxX - minX) * xFactor, (maxY - minY) * yFactor, g => { g.Clear(settings.MemoryBackgroundColor); using (var unusedEdgePen = new Pen(settings.MemoryGridZeroColor)) using (var usedEdgePen = new Pen(settings.MemoryGridNonZeroColor, 2f)) using (var pointerBrush = new SolidBrush(settings.MemoryPointerColor)) using (var valueBrush = new SolidBrush(settings.MemoryValueFont.NullOr(f => f.Color) ?? Color.CornflowerBlue)) using (var annotationBrush = new SolidBrush(settings.MemoryAnnotationFont.NullOr(f => f.Color) ?? Color.ForestGreen)) using (var valueFont = settings.MemoryValueFont.NullOr(f => f.Font)) using (var annotationFont = settings.MemoryAnnotationFont.NullOr(f => f.Font)) { var sfValue = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Near }; var sfAnnotation = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Far }; for (int y = minY; y <= maxY; y++) { for (int x = minX; x <= maxX; x++) { if (!((y % 2 == 0 && x % 2 == 0) || ((y % 4 + 4) % 4 == 1 && (x % 4 + 4) % 4 == 1) || ((y % 4 + 4) % 4 == 3 && (x % 4 + 4) % 4 == 3))) { continue; } var dir = Direction.East; var mp = new PointAxial(0, 0); if (y % 2 != 0) { dir = Direction.East; mp = new PointAxial((x - y) / 4, (y - 1) / 2); } else if ((x - y) % 4 == 0) { dir = Direction.NorthEast; mp = new PointAxial((x - y) / 4, y / 2); } else { dir = Direction.SouthEast; mp = new PointAxial((x - y + 2) / 4, (y - 2) / 2); } var xx = (x - minX) * xFactor; var yy = (y - minY) * yFactor; var hasValue = _edges.ContainsKeys(dir, mp); using (var tr = new GraphicsTransformer(g).Rotate((dir is NorthEast ? -60 : dir is SouthEast ? 60 : 0) + (_cw ? 180 : 0)).Translate(xx, yy)) { g.DrawLine(hasValue ? usedEdgePen : unusedEdgePen, 0, yFactor * -.68f, 0, yFactor * .68f); if (dir == _dir && mp == _mp) { g.FillPolygon(pointerBrush, new[] { new PointF(0, yFactor * -.68f), new PointF(3, yFactor * .68f), new PointF(-3, yFactor * .68f) }); } } using (var tr = new GraphicsTransformer(g).Rotate((dir is NorthEast ? 30 : dir is SouthEast ? -30 : -90)).Translate(xx, yy)) { if (hasValue) { var str = _edges[dir][mp].ToString(); // Show printable ISO-8859-1 characters if (_edges[dir][mp] >= 0x20 && _edges[dir][mp] <= 0xff && _edges[dir][mp] != 0x7f) { try { str += " '" + char.ConvertFromUtf32((int)_edges[dir][mp]) + "'"; } catch { } } g.DrawString(str, valueFont ?? defaultValueFont, valueBrush, 0, 0, sfValue); } var annotation = _annotations.Get(dir, mp, null); if (!string.IsNullOrWhiteSpace(annotation)) { g.DrawString(annotation, annotationFont ?? defaultAnnotationFont, annotationBrush, 0, 2, sfAnnotation); } } } } } })); }