public static Blueprint Generate(SpriteMemoryConfiguration configuration)
        {
            var spriteCount = configuration.SpriteCount ?? 16;
            var baseAddress = configuration.BaseAddress ?? 1;

            var rowSignals  = ComputerSignals.OrderedSignals.Take(36).ToList();
            var inputSignal = VirtualSignalNames.LetterOrDigit('0');

            var entities   = new List <Entity>();
            var sprites    = new Sprite[spriteCount];
            var rowFilters = new RowFilter[rowSignals.Count + 1];

            for (var index = 0; index < spriteCount; index++)
            {
                var reader = new Entity
                {
                    Name     = ItemNames.DeciderCombinator,
                    Position = new Position
                    {
                        X = 0.5,
                        Y = index
                    },
                    Direction        = Direction.Left,
                    Control_behavior = new ControlBehavior
                    {
                        Decider_conditions = new DeciderConditions
                        {
                            First_signal          = SignalID.Create(VirtualSignalNames.Check),
                            Constant              = 0,
                            Comparator            = Comparators.IsEqual,
                            Output_signal         = SignalID.Create(VirtualSignalNames.Everything),
                            Copy_count_from_input = true
                        }
                    }
                };
                entities.Add(reader);

                var drawSelector = new Entity
                {
                    Name     = ItemNames.DeciderCombinator,
                    Position = new Position
                    {
                        X = 2.5,
                        Y = index
                    },
                    Direction        = Direction.Left,
                    Control_behavior = new ControlBehavior
                    {
                        Decider_conditions = new DeciderConditions
                        {
                            First_signal          = SignalID.Create(VirtualSignalNames.Dot),
                            Constant              = index + 1,
                            Comparator            = Comparators.IsEqual,
                            Output_signal         = SignalID.Create(VirtualSignalNames.Everything),
                            Copy_count_from_input = true
                        }
                    }
                };
                entities.Add(drawSelector);

                var memory = new Entity
                {
                    Name     = ItemNames.DeciderCombinator,
                    Position = new Position
                    {
                        X = 4.5,
                        Y = index
                    },
                    Direction        = Direction.Left,
                    Control_behavior = new ControlBehavior
                    {
                        Decider_conditions = new DeciderConditions
                        {
                            First_signal          = SignalID.Create(VirtualSignalNames.Info),
                            Constant              = 0,
                            Comparator            = Comparators.IsEqual,
                            Output_signal         = SignalID.Create(VirtualSignalNames.Everything),
                            Copy_count_from_input = true
                        }
                    }
                };
                entities.Add(memory);

                var writer = new Entity
                {
                    Name     = ItemNames.DeciderCombinator,
                    Position = new Position
                    {
                        X = 6.5,
                        Y = index
                    },
                    Direction        = Direction.Left,
                    Control_behavior = new ControlBehavior
                    {
                        Decider_conditions = new DeciderConditions
                        {
                            First_signal          = SignalID.Create(VirtualSignalNames.Check),
                            Constant              = 0,
                            Comparator            = Comparators.IsEqual,
                            Output_signal         = SignalID.Create(VirtualSignalNames.Everything),
                            Copy_count_from_input = true
                        }
                    }
                };
                entities.Add(writer);

                var spriteSelector = new Entity
                {
                    Name     = ItemNames.DeciderCombinator,
                    Position = new Position
                    {
                        X = 8.5,
                        Y = index
                    },
                    Direction        = Direction.Left,
                    Control_behavior = new ControlBehavior
                    {
                        Decider_conditions = new DeciderConditions
                        {
                            First_signal          = SignalID.Create(VirtualSignalNames.Info),
                            Constant              = index + 1,
                            Comparator            = Comparators.IsNotEqual,
                            Output_signal         = SignalID.Create(VirtualSignalNames.Check),
                            Copy_count_from_input = false
                        }
                    }
                };
                entities.Add(spriteSelector);

                sprites[index] = new Sprite
                {
                    Reader         = reader,
                    DrawSelector   = drawSelector,
                    Memory         = memory,
                    Writer         = writer,
                    SpriteSelector = spriteSelector
                };
            }

            for (var index = 0; index < rowFilters.Length; index++)
            {
                var renamer = new Entity
                {
                    Name     = index == 0 ? ItemNames.DeciderCombinator : ItemNames.ArithmeticCombinator,
                    Position = new Position
                    {
                        X = 10.5,
                        Y = index
                    },
                    Direction        = Direction.Left,
                    Control_behavior = index == 0
                        ? new ControlBehavior
                    {
                        Decider_conditions = new DeciderConditions
                        {
                            First_signal          = SignalID.Create(inputSignal),
                            Constant              = 1,
                            Comparator            = Comparators.IsEqual,
                            Output_signal         = SignalID.Create(VirtualSignalNames.Info),
                            Copy_count_from_input = false
                        }
                    }
                        : new ControlBehavior
                    {
                        Arithmetic_conditions = new ArithmeticConditions
                        {
                            First_signal    = SignalID.Create(inputSignal),
                            Second_constant = 1,
                            Operation       = ArithmeticOperations.Multiplication,
                            Output_signal   = SignalID.Create(rowSignals[index - 1])
                        }
                    }
                };
                entities.Add(renamer);

                var addressMatcher = new Entity
                {
                    Name     = ItemNames.DeciderCombinator,
                    Position = new Position
                    {
                        X = 12.5,
                        Y = index
                    },
                    Direction        = Direction.Left,
                    Control_behavior = new ControlBehavior
                    {
                        Decider_conditions = new DeciderConditions
                        {
                            First_signal          = SignalID.Create(VirtualSignalNames.Check),
                            Constant              = baseAddress + index,
                            Comparator            = Comparators.IsEqual,
                            Output_signal         = SignalID.Create(inputSignal),
                            Copy_count_from_input = true
                        }
                    }
                };
                entities.Add(addressMatcher);

                rowFilters[index] = new RowFilter
                {
                    Renamer        = renamer,
                    AddressMatcher = addressMatcher
                };
            }

            BlueprintUtil.PopulateEntityNumbers(entities);

            AddConnection(CircuitColor.Green, sprites[0].Writer, CircuitId.Input, rowFilters[0].Renamer, CircuitId.Output);

            for (var index = 0; index < spriteCount; index++)
            {
                var sprite = sprites[index];

                AddConnection(CircuitColor.Green, sprite.Reader, CircuitId.Input, sprite.DrawSelector, CircuitId.Input);
                AddConnection(CircuitColor.Green, sprite.DrawSelector, CircuitId.Input, sprite.Memory, CircuitId.Output);
                AddConnection(CircuitColor.Green, sprite.Memory, CircuitId.Output, sprite.Memory, CircuitId.Input);
                AddConnection(CircuitColor.Red, sprite.Memory, CircuitId.Input, sprite.Writer, CircuitId.Output);
                AddConnection(CircuitColor.Red, sprite.Reader, CircuitId.Input, sprite.Writer, CircuitId.Input);
                AddConnection(CircuitColor.Red, sprite.Writer, CircuitId.Input, sprite.SpriteSelector, CircuitId.Output);

                if (index > 0)
                {
                    var adjacentSprite = sprites[index - 1];

                    AddConnection(CircuitColor.Green, sprite.Reader, CircuitId.Output, adjacentSprite.Reader, CircuitId.Output);
                    AddConnection(CircuitColor.Green, sprite.DrawSelector, CircuitId.Output, adjacentSprite.DrawSelector, CircuitId.Output);
                    AddConnection(CircuitColor.Red, sprite.DrawSelector, CircuitId.Input, adjacentSprite.DrawSelector, CircuitId.Input);
                    AddConnection(CircuitColor.Green, sprite.Writer, CircuitId.Input, adjacentSprite.Writer, CircuitId.Input);
                    AddConnection(CircuitColor.Green, sprite.SpriteSelector, CircuitId.Input, adjacentSprite.SpriteSelector, CircuitId.Input);
                }
            }

            for (var index = 0; index < rowFilters.Length; index++)
            {
                var rowFilter = rowFilters[index];

                AddConnection(CircuitColor.Green, rowFilter.Renamer, CircuitId.Input, rowFilter.AddressMatcher, CircuitId.Output);

                if (index > 0)
                {
                    var adjacentRowFilter = rowFilters[index - 1];

                    AddConnection(CircuitColor.Green, rowFilter.Renamer, CircuitId.Output, adjacentRowFilter.Renamer, CircuitId.Output);
                    AddConnection(CircuitColor.Green, rowFilter.AddressMatcher, CircuitId.Input, adjacentRowFilter.AddressMatcher, CircuitId.Input);
                    AddConnection(CircuitColor.Red, rowFilter.AddressMatcher, CircuitId.Input, adjacentRowFilter.AddressMatcher, CircuitId.Input);
                }
            }

            return(new Blueprint
            {
                Label = $"Sprite Memory",
                Icons = new List <Icon>
                {
                    Icon.Create(ItemNames.DeciderCombinator),
                    Icon.Create(ItemNames.Lamp)
                },
                Entities = entities,
                Item = ItemNames.Blueprint,
                Version = BlueprintVersions.CurrentVersion
            });
        }
コード例 #2
0
 private static Filter CreateFilter(char signal, int count)
 {
     return(Filter.Create(VirtualSignalNames.LetterOrDigit(signal), count));
 }
コード例 #3
0
        public static Blueprint Generate(VideoMemoryConfiguration configuration, List <bool[, ]> frames = null)
        {
            var width       = configuration.Width ?? 32;
            var height      = configuration.Height ?? 2;
            var baseAddress = configuration.BaseAddress ?? 1;

            var frameHeight = frames?.ElementAtOrDefault(0)?.GetLength(0) ?? 0;

            const int framesPerRow = 32;
            const int maxFilters   = 20;

            var entities   = new List <Entity>();
            var memoryRows = new MemoryRow[height];

            var metadata = new Entity
            {
                Name     = ItemNames.ConstantCombinator,
                Position = new Position
                {
                    X = 2,
                    Y = 0
                },
                Direction        = Direction.Down,
                Control_behavior = new ControlBehavior
                {
                    Filters = new List <Filter>
                    {
                        Filter.Create(VirtualSignalNames.LetterOrDigit('Z'), frames?.Count ?? 0)
                    }
                }
            };

            entities.Add(metadata);

            for (var row = 0; row < height; row++)
            {
                var cellY     = row * 9 - (row % 2 == 1 ? 1 : 0) + 2;
                var rowFrames = frames?.Skip(row * framesPerRow).Take(framesPerRow).ToList();

                var addressMatcher = new Entity
                {
                    Name     = ItemNames.DeciderCombinator,
                    Position = new Position
                    {
                        X = 1,
                        Y = cellY + 0.5
                    },
                    Direction        = Direction.Down,
                    Control_behavior = new ControlBehavior
                    {
                        Decider_conditions = new DeciderConditions
                        {
                            First_signal          = SignalID.Create(VirtualSignalNames.Info),
                            Constant              = row + baseAddress,
                            Comparator            = Comparators.IsNotEqual,
                            Output_signal         = SignalID.Create(VirtualSignalNames.Check),
                            Copy_count_from_input = false
                        }
                    }
                };
                entities.Add(addressMatcher);

                var memoryCells = new MemoryCell[width];

                for (var column = 0; column < width; column++)
                {
                    var cellX = column + 2;

                    var enabler = new Entity
                    {
                        Name     = ItemNames.DeciderCombinator,
                        Position = new Position
                        {
                            X = cellX,
                            Y = cellY + 0.5
                        },
                        Direction        = Direction.Up,
                        Control_behavior = new ControlBehavior
                        {
                            Decider_conditions = new DeciderConditions
                            {
                                First_signal          = SignalID.Create(VirtualSignalNames.Check),
                                Constant              = 0,
                                Comparator            = Comparators.IsEqual,
                                Output_signal         = SignalID.Create(VirtualSignalNames.Everything),
                                Copy_count_from_input = true
                            }
                        }
                    };
                    entities.Add(enabler);

                    var pixelFilters = Enumerable.Range(0, frameHeight)
                                       .Select(frameRow =>
                    {
                        var pixel = rowFrames
                                    .Select((frame, frameOffset) => frame[frameRow, column] ? 1 << frameOffset : 0)
                                    .Sum();

                        return(Filter.Create(ScreenUtil.PixelSignals[frameRow], pixel));
                    })
                                       .Where(pixelFilter => pixelFilter.Count != 0)
                                       .ToList();

                    var subCellCount = column % 18 >= 16 ? 6 : 7;
                    var subCells     = new Entity[subCellCount];

                    for (var subCellIndex = 0; subCellIndex < subCellCount; subCellIndex++)
                    {
                        var subCell = new Entity
                        {
                            Name     = ItemNames.ConstantCombinator,
                            Position = new Position
                            {
                                X = cellX,
                                Y = subCellIndex < 6 || row % 2 == 1 ? cellY + subCellIndex + 2 : cellY - 1
                            },
                            Direction        = Direction.Down,
                            Control_behavior = new ControlBehavior
                            {
                                Filters = pixelFilters.Skip(subCellIndex * maxFilters).Take(maxFilters).ToList()
                            }
                        };
                        entities.Add(subCell);
                        subCells[subCellIndex] = subCell;
                    }

                    memoryCells[column] = new MemoryCell
                    {
                        Enabler  = enabler,
                        SubCells = subCells
                    };
                }

                memoryRows[row] = new MemoryRow
                {
                    AddressMatcher = addressMatcher,
                    Cells          = memoryCells
                };
            }

            BlueprintUtil.PopulateEntityNumbers(entities);

            var substationWidth  = (width + 9) / 18 + 1;
            var substationHeight = height / 2 + 1;

            entities.AddRange(CreateSubstations(substationWidth, substationHeight, 0, 0, entities.Count + 1));

            for (var row = 0; row < height; row++)
            {
                var memoryRow = memoryRows[row];

                AddConnection(CircuitColor.Red, memoryRow.AddressMatcher, CircuitId.Output, memoryRow.Cells[0].Enabler, CircuitId.Input);

                var adjacentRow = row - 1;
                if (adjacentRow >= 0)
                {
                    var adjacentMemoryRow = memoryRows[adjacentRow];

                    AddConnection(CircuitColor.Green, memoryRow.AddressMatcher, CircuitId.Input, adjacentMemoryRow.AddressMatcher, CircuitId.Input);

                    for (var column = 0; column < width; column++)
                    {
                        var memoryCell         = memoryRow.Cells[column];
                        var adjacentMemoryCell = adjacentMemoryRow.Cells[column];

                        AddConnection(CircuitColor.Green, memoryCell.Enabler, CircuitId.Output, adjacentMemoryCell.Enabler, CircuitId.Output);
                    }
                }

                for (var column = 0; column < width; column++)
                {
                    var memoryCell = memoryRow.Cells[column];

                    AddConnection(CircuitColor.Green, memoryCell.SubCells[0], null, memoryCell.Enabler, CircuitId.Input);

                    for (var subCellIndex = 1; subCellIndex < memoryCell.SubCells.Length; subCellIndex++)
                    {
                        var subCell         = memoryCell.SubCells[subCellIndex];
                        var adjacentSubCell = memoryCell.SubCells[subCellIndex < 6 || row % 2 == 1 ? subCellIndex - 1 : 0];

                        AddConnection(CircuitColor.Green, subCell, null, adjacentSubCell, null);
                    }

                    var adjacentColumn = column - 1;
                    if (adjacentColumn >= 0)
                    {
                        var adjacentMemoryCell = memoryRow.Cells[adjacentColumn];

                        AddConnection(CircuitColor.Red, memoryCell.Enabler, CircuitId.Input, adjacentMemoryCell.Enabler, CircuitId.Input);
                    }
                }
            }

            return(new Blueprint
            {
                Label = $"Video ROM",
                Icons = new List <Icon>
                {
                    Icon.Create(ItemNames.Lamp),
                    Icon.Create(ItemNames.ConstantCombinator)
                },
                Entities = entities,
                Item = ItemNames.Blueprint,
                Version = BlueprintVersions.CurrentVersion
            });
        }
コード例 #4
0
        public static Blueprint Generate(RomConfiguration configuration, IList <MemoryCell> program = null, IList <MemoryCell> data = null)
        {
            var snapToGrid  = configuration.SnapToGrid ?? false;
            var xOffset     = configuration.X ?? 0;
            var yOffset     = configuration.Y ?? 0;
            var width       = configuration.Width ?? 16;
            var height      = configuration.Height ?? 16;
            var cellSize    = configuration.CellSize ?? 1;
            var programRows = configuration.ProgramRows ?? (program != null ? (program.Count - 1) / width + 1 : height / 2);
            var programName = configuration.ProgramName;
            var iconNames   = configuration.IconNames ?? new List <string> {
                ItemNames.ElectronicCircuit
            };

            if (program != null && program.Count > programRows * width)
            {
                Console.WriteLine($"Program too large to fit in ROM ({program.Count} > {programRows * width})");
                programRows = (program.Count - 1) / width + 1;
                height      = Math.Max(height, programRows + ((data?.Count ?? 0) - 1) / width + 1);
            }

            if (data != null && data.Count > (height - programRows) * width)
            {
                Console.WriteLine($"Data too large to fit in ROM ({data.Count} > {(height - programRows) * width})");
                height = programRows + (data.Count - 1) / width + 1;
            }

            const int maxFilters = 20;

            var entitiesPerCell    = cellSize + 1;
            var cellHeight         = cellSize + 2;
            var blockHeightInCells = 64 * 3 / (cellSize + 2);
            var blockGapHeight     = 8;

            var readerEntityOffset = cellSize;

            var gridWidth  = width + ((width + 7) / 16 + 1) * 2;
            var gridHeight = height * cellHeight + (height - 1) / blockHeightInCells * blockGapHeight;

            var entities = new List <Entity>();

            for (int row = 0; row < height; row++)
            {
                for (int column = 0; column < width; column++)
                {
                    var memoryCell = row < programRows
                        ? program?.ElementAtOrDefault(row *width + column) ?? new MemoryCell
                    {
                        Address = -1, IsEnabled = false
                    }

                        : data?.ElementAtOrDefault((row - programRows) * width + column) ?? new MemoryCell {
                        Address = -1, IsEnabled = false
                    };
                    var memoryCellEntityNumber = (row * width + column) * entitiesPerCell + 1;
                    var memoryCellX            = column + (column / 16 + 1) * 2 + xOffset;
                    var memoryCellY            = gridHeight - (row + 1) * cellHeight - row / blockHeightInCells * blockGapHeight + yOffset;

                    var adjacentMemoryCells = new List <int> {
                        -1, 1
                    }
                    .Where(offset => column + offset >= 0 && column + offset < width)
                    .Select(offset => memoryCellEntityNumber + offset * entitiesPerCell)
                    .Concat(new List <int> {
                        -1, 1
                    }
                            .Where(offset => row + offset >= 0 && row + offset < height && (row < programRows == row + offset < programRows) && column == 0)
                            .Select(offset => memoryCellEntityNumber + offset * width * entitiesPerCell)
                            )
                    .ToList();

                    // Memory sub-cells
                    for (var subCell = 0; subCell < cellSize; subCell++)
                    {
                        entities.Add(new Entity
                        {
                            Entity_number = memoryCellEntityNumber + subCell,
                            Name          = ItemNames.ConstantCombinator,
                            Position      = new Position
                            {
                                X = memoryCellX,
                                Y = memoryCellY + cellSize - subCell - 1
                            },
                            Direction        = Direction.Down,
                            Control_behavior = new ControlBehavior
                            {
                                Filters = memoryCell.Filters?.Skip(subCell * maxFilters).Take(maxFilters).ToList(),
                                Is_on   = memoryCell.IsEnabled ? (bool?)null : false
                            },
                            Connections = CreateConnections(new ConnectionPoint
                            {
                                Green = new List <ConnectionData>
                                {
                                    // Connection to reader input or previous memory sub-cell
                                    new ConnectionData
                                    {
                                        Entity_id  = memoryCellEntityNumber + (subCell == 0 ? readerEntityOffset : subCell - 1),
                                        Circuit_id = CircuitId.Input
                                    }
                                }
                            })
                        });
                    }

                    // Memory cell reader
                    entities.Add(new Entity
                    {
                        Entity_number = memoryCellEntityNumber + readerEntityOffset,
                        Name          = ItemNames.DeciderCombinator,
                        Position      = new Position
                        {
                            X = memoryCellX,
                            Y = memoryCellY + cellSize + 0.5
                        },
                        Direction        = Direction.Down,
                        Control_behavior = new ControlBehavior
                        {
                            Decider_conditions = new DeciderConditions
                            {
                                First_signal          = SignalID.CreateVirtual(VirtualSignalNames.Info),
                                Constant              = memoryCell.Address,
                                Comparator            = Comparators.IsEqual,
                                Output_signal         = SignalID.CreateVirtual(VirtualSignalNames.Everything),
                                Copy_count_from_input = true
                            }
                        },
                        Connections = CreateConnections(new ConnectionPoint
                        {
                            // Connection to adjacent reader input (address line)
                            Red = adjacentMemoryCells.Select(entityNumber => new ConnectionData
                            {
                                Entity_id  = entityNumber + readerEntityOffset,
                                Circuit_id = CircuitId.Input
                            }).ToList(),
                            Green = new List <ConnectionData>
                            {
                                // Connection to memory cell
                                new ConnectionData
                                {
                                    Entity_id = memoryCellEntityNumber
                                }
                            }
                        }, new ConnectionPoint
                        {
                            // Connection to adjacent reader output
                            Green = adjacentMemoryCells.Select(entityNumber => new ConnectionData
                            {
                                Entity_id  = entityNumber + readerEntityOffset,
                                Circuit_id = CircuitId.Output
                            }).ToList()
                        })
                    });
                }
            }

            // Timestamp
            entities.Add(new Entity
            {
                Entity_number = entities.Count + 1,
                Name          = ItemNames.ConstantCombinator,
                Position      = new Position
                {
                    X = 1 + xOffset,
                    Y = gridHeight - 2 + yOffset
                },
                Direction        = Direction.Down,
                Control_behavior = new ControlBehavior
                {
                    Filters = new List <Filter>
                    {
                        Filter.Create(VirtualSignalNames.LetterOrDigit('0'), (int)(DateTime.Now.Ticks / 10000))
                    }
                }
            });

            var substationWidth  = (width + 7) / 16 + 1;
            var substationHeight = (gridHeight + 2) / 18 + 1;

            entities.AddRange(CreateSubstations(substationWidth, substationHeight, xOffset, gridHeight % 18 - 4 + yOffset, entities.Count + 1));

            return(new Blueprint
            {
                Label = $"{width}x{height} ROM{(programName != null ? $": {programName}": "")}",
                Icons = iconNames.Select(name => Icon.Create(name)).ToList(),
                Entities = entities,
                SnapToGrid = snapToGrid ? new SnapToGrid {
                    X = (ulong)gridWidth, Y = (ulong)gridHeight
                } : null,
                AbsoluteSnapping = snapToGrid ? true : null,
                Item = ItemNames.Blueprint,
                Version = BlueprintVersions.CurrentVersion
            });
        }
コード例 #5
0
 public static SignalID CreateLetterOrDigit(char letterOrDigit)
 {
     return(CreateVirtual(VirtualSignalNames.LetterOrDigit(letterOrDigit)));
 }
コード例 #6
0
        public static Blueprint Generate(FontConfiguration configuration)
        {
            var fontImageFile      = configuration.FontImage;
            var combinatorsPerRow  = configuration.CombinatorsPerRow ?? 5;
            var useOneSignalPerRow = configuration.UseOneSignalPerRow ?? false;
            var inputSignal        = configuration.InputSignal ?? VirtualSignalNames.Dot;
            var widthSignal        = configuration.WidthSignal;
            var heightSignal       = configuration.HeightSignal;
            var signals            = configuration.Signals.Contains(',') ? configuration.Signals.Split(',').ToList() : configuration.Signals.Select(signal => VirtualSignalNames.LetterOrDigit(signal)).ToList();

            const int maxFilters = 20;

            var font       = FontUtil.ReadFont(fontImageFile);
            var characters = font.Characters;

            var entities          = new List <Entity>();
            var characterEntities = new List <(Entity Matcher, List <Entity> Glyph)>();

            if (heightSignal != null)
            {
                characters.Add(new FontUtil.Character
                {
                    CharacterCode = '\n',
                    GlyphPixels   = new bool[font.Height, 0]
                });
            }

            var combinatorX = 0;

            for (var characterIndex = 0; characterIndex < characters.Count; characterIndex++)
            {
                var character   = characters[characterIndex];
                var glyphPixels = character.GlyphPixels;
                var height      = glyphPixels.GetLength(0);
                var width       = glyphPixels.GetLength(1);

                if (characterIndex % combinatorsPerRow == 0)
                {
                    combinatorX = 0;
                }

                var glyphFilters = new List <Filter>();

                if (widthSignal != null)
                {
                    glyphFilters.Add(Filter.Create(widthSignal, width));
                }

                if (heightSignal != null)
                {
                    glyphFilters.Add(Filter.Create(heightSignal, height));
                }

                for (int y = 0; y < height; y++)
                {
                    if (useOneSignalPerRow)
                    {
                        var rowSignal = 0;

                        for (int x = 0; x < width; x++)
                        {
                            if (glyphPixels[y, x])
                            {
                                rowSignal |= 1 << x;
                            }
                        }

                        glyphFilters.Add(Filter.Create(signals[y], rowSignal));
                    }
                    else
                    {
                        for (int x = 0; x < width; x++)
                        {
                            if (glyphPixels[y, x])
                            {
                                glyphFilters.Add(Filter.Create(signals[y * width + x]));
                            }
                        }
                    }
                }

                var combinatorY = characterIndex / combinatorsPerRow;

                var matcher = new Entity
                {
                    Name     = ItemNames.DeciderCombinator,
                    Position = new Position
                    {
                        X = (characterIndex % combinatorsPerRow - combinatorsPerRow) * 2 + 0.5,
                        Y = combinatorY
                    },
                    Direction        = Direction.Left,
                    Control_behavior = new ControlBehavior
                    {
                        Decider_conditions = new DeciderConditions
                        {
                            First_signal          = SignalID.Create(inputSignal),
                            Constant              = character.CharacterCode,
                            Comparator            = Comparators.IsEqual,
                            Output_signal         = SignalID.Create(VirtualSignalNames.Everything),
                            Copy_count_from_input = true
                        }
                    }
                };
                entities.Add(matcher);

                var glyph = new List <Entity>();

                for (int index = 0; index < (glyphFilters.Count + maxFilters - 1) / maxFilters; index++)
                {
                    var glyphPart = new Entity
                    {
                        Name     = ItemNames.ConstantCombinator,
                        Position = new Position
                        {
                            X = combinatorX++,
                            Y = combinatorY
                        },
                        Direction        = Direction.Down,
                        Control_behavior = new ControlBehavior
                        {
                            Filters = glyphFilters.Skip(index * maxFilters).Take(maxFilters).ToList()
                        }
                    };
                    glyph.Add(glyphPart);
                    entities.Add(glyphPart);
                }

                characterEntities.Add((matcher, glyph));
            }

            BlueprintUtil.PopulateEntityNumbers(entities);

            for (int characterIndex = 0; characterIndex < characterEntities.Count; characterIndex++)
            {
                var(matcher, glyph) = characterEntities[characterIndex];

                AddConnection(CircuitColor.Green, matcher, CircuitId.Input, glyph[0], null); // Connect to constant combinators holding glyphs

                var adjacentCharacterIndex = characterIndex - (characterIndex / combinatorsPerRow == 0 ? 1 : combinatorsPerRow);
                if (adjacentCharacterIndex >= 0)
                {
                    var adjacentMatcher = characterEntities[adjacentCharacterIndex].Matcher;

                    AddConnection(CircuitColor.Red, matcher, CircuitId.Input, adjacentMatcher, CircuitId.Input);     // Connect inputs together
                    AddConnection(CircuitColor.Green, matcher, CircuitId.Output, adjacentMatcher, CircuitId.Output); // Connect outputs together
                }

                // Connections between glyph parts
                for (int index = 1; index < glyph.Count; index++)
                {
                    AddConnection(CircuitColor.Green, glyph[index], null, glyph[index - 1], null);
                }
            }

            return(new Blueprint
            {
                Label = $"{font.Width}x{font.Height} Font",
                Icons = new List <Icon>
                {
                    Icon.Create(ItemNames.ConstantCombinator),
                    Icon.Create(VirtualSignalNames.LetterOrDigit('A')),
                    Icon.Create(VirtualSignalNames.LetterOrDigit('B')),
                    Icon.Create(VirtualSignalNames.LetterOrDigit('C'))
                },
                Entities = entities,
                Item = ItemNames.Blueprint,
                Version = BlueprintVersions.CurrentVersion
            });
        }
コード例 #7
0
        public static Blueprint Generate(DemuxConfiguration configuration)
        {
            var signalCount   = configuration.SignalCount ?? ComputerSignals.OrderedSignals.Count;
            var width         = configuration.Width ?? 1;
            var addressSignal = configuration.AddressSignal ?? VirtualSignalNames.Dot;
            var outputSignal  = configuration.OutputSignal ?? VirtualSignalNames.LetterOrDigit('A');

            var entities      = new List <Entity>();
            var signalFilters = new SignalFilter[signalCount];

            for (int index = 0; index < signalCount; index++)
            {
                var filterX = index % width * 4;
                var filterY = index / width;

                var addressChecker = new Entity
                {
                    Name     = ItemNames.DeciderCombinator,
                    Position = new Position
                    {
                        X = 0.5 + filterX,
                        Y = filterY
                    },
                    Direction        = Direction.Right,
                    Control_behavior = new ControlBehavior
                    {
                        Decider_conditions = new DeciderConditions
                        {
                            First_signal          = SignalID.Create(addressSignal),
                            Constant              = index + 1,
                            Comparator            = Comparators.IsEqual,
                            Output_signal         = SignalID.Create(VirtualSignalNames.Dot),
                            Copy_count_from_input = false
                        }
                    }
                };
                entities.Add(addressChecker);

                var signalRenamer = new Entity
                {
                    Name     = ItemNames.ArithmeticCombinator,
                    Position = new Position
                    {
                        X = 2.5 + filterX,
                        Y = filterY
                    },
                    Direction        = Direction.Right,
                    Control_behavior = new ControlBehavior
                    {
                        Arithmetic_conditions = new ArithmeticConditions
                        {
                            First_signal  = SignalID.Create(ComputerSignals.OrderedSignals[index]),
                            Second_signal = SignalID.Create(VirtualSignalNames.Dot),
                            Operation     = ArithmeticOperations.Multiplication,
                            Output_signal = SignalID.Create(outputSignal)
                        }
                    }
                };
                entities.Add(signalRenamer);

                signalFilters[index] = new SignalFilter
                {
                    AddressChecker = addressChecker,
                    SignalRenamer  = signalRenamer
                };
            }

            BlueprintUtil.PopulateEntityNumbers(entities);

            for (var index = 0; index < signalCount; index++)
            {
                var signalFilter = signalFilters[index];

                AddConnection(CircuitColor.Red, signalFilter.AddressChecker, CircuitId.Output, signalFilter.SignalRenamer, CircuitId.Input);

                if (index > 0)
                {
                    var adjacentSignalFilterIndex = index / width == 0 ? index - 1 : index - width;
                    var adjacentSignalFilter      = signalFilters[adjacentSignalFilterIndex];

                    AddConnection(CircuitColor.Red, signalFilter.AddressChecker, CircuitId.Input, adjacentSignalFilter.AddressChecker, CircuitId.Input);
                    AddConnection(CircuitColor.Green, signalFilter.SignalRenamer, CircuitId.Input, adjacentSignalFilter.SignalRenamer, CircuitId.Input);
                    AddConnection(CircuitColor.Red, signalFilter.SignalRenamer, CircuitId.Output, adjacentSignalFilter.SignalRenamer, CircuitId.Output);
                }
            }

            return(new Blueprint
            {
                Label = $"Demultiplexer",
                Icons = new List <Icon>
                {
                    Icon.Create(ItemNames.DeciderCombinator),
                    Icon.Create(ItemNames.ArithmeticCombinator)
                },
                Entities = entities,
                Item = ItemNames.Blueprint,
                Version = BlueprintVersions.CurrentVersion
            });
        }