Example #1
0
        public ProgramCounter(int row, int col, PlayField playField)
        {
            Row        = row;
            Col        = col;
            _playField = playField;

            Directions = new Dictionary <ProgramCounterDirection, Action> {
                { ProgramCounterDirection.Up, MoveUp },
                { ProgramCounterDirection.Down, MoveDown },
                { ProgramCounterDirection.Left, MoveLeft },
                { ProgramCounterDirection.Right, MoveRight },
            };
        }
Example #2
0
        static void Main(string[] args)
        {
            var debug    = args.Any(arg => arg == "--debug");
            var filename = args.FirstOrDefault(arg => !arg.StartsWith("--"));

            if (filename == null)
            {
                Console.WriteLine("Usage: befunge <source.bf> [--debug]");
                Environment.Exit(1);
            }

            if (!File.Exists(filename))
            {
                Console.WriteLine($"Invalid filename: {args[0]}");
                Environment.Exit(1);
            }

            var source = File.OpenText(args[0]).ReadToEnd();

            if (debug)
            {
                Console.Error.WriteLine(source);
            }

            if (debug)
            {
                Console.Error.WriteLine("Tokenizing...");
            }
            var tokenizer = new Tokenizer(source);
            var tokens    = tokenizer.Tokenize();

            if (debug)
            {
                Console.Error.WriteLine("Creating the playing field...");
            }
            var field = new PlayField(tokens);

            if (debug)
            {
                Console.Error.WriteLine("Running the VM...");
            }
            new VirtualMachine().Run(field, debug);

            Console.WriteLine();
        }
Example #3
0
        public void Run(PlayField playField, bool debug = false)
        {
            var stack = new Stack <long>();

            var stringMode = false;

            var randomForDirection  = new Random();
            var availableDirections = new[] {
                ProgramCounterDirection.Up, ProgramCounterDirection.Down,
                ProgramCounterDirection.Left, ProgramCounterDirection.Right,
            };
            var currentDirection = ProgramCounterDirection.Right;

            while (true)
            {
                if (debug)
                {
                    if (!(playField.Current is BlankToken))
                    {
                        Console.Error.WriteLine(
                            $"Stack: {string.Join(", ", stack.ToList())} ");
                        Console.Error.WriteLine(playField.Current);
                    }
                }

                if (stringMode)
                {
                    if (playField.Current is QuoteToken)
                    {
                        stringMode = !stringMode;
                    }
                    else
                    {
                        stack.Push(playField.Current.AsCharToken().AsciiValue);
                    }
                }
                else
                {
                    long a, b;
                    switch (playField.Current)
                    {
                    case AddToken t:
                        (a, b) = (stack.PopOrZero(), stack.PopOrZero());
                        stack.Push(a + b);
                        break;

                    case SubtractToken t:
                        (a, b) = (stack.PopOrZero(), stack.PopOrZero());
                        stack.Push(b - a);
                        break;

                    case MultiplyToken t:
                        (a, b) = (stack.PopOrZero(), stack.PopOrZero());
                        stack.Push(a * b);
                        break;

                    case DivideToken t:
                        (a, b) = (stack.PopOrZero(), stack.PopOrZero());
                        if (a != 0)
                        {
                            stack.Push(b / a);
                        }
                        else
                        {
                            stack.Push(
                                PromptForInt("Can't divide by zero. What result would you like?")
                                );
                        }
                        break;

                    case ModulusToken t:
                        (a, b) = (stack.PopOrZero(), stack.PopOrZero());
                        stack.Push(b % a);
                        break;

                    case NotToken t:
                        a = stack.PopOrZero();
                        stack.Push(a == 0 ? 1 : 0);
                        break;

                    case GreaterToken t:
                        (a, b) = (stack.PopOrZero(), stack.PopOrZero());
                        stack.Push(b > a ? 1 : 0);
                        break;

                    case RightToken t:
                        currentDirection = ProgramCounterDirection.Right;
                        break;

                    case LeftToken t:
                        currentDirection = ProgramCounterDirection.Left;
                        break;

                    case UpToken t:
                        currentDirection = ProgramCounterDirection.Up;
                        break;

                    case DownToken t:
                        currentDirection = ProgramCounterDirection.Down;
                        break;

                    case RandomToken t:
                        currentDirection =
                            availableDirections[randomForDirection.Next(availableDirections.Length)];
                        break;

                    case HorizontalIfToken t:
                        a = stack.PopOrZero();
                        currentDirection = a == 0
                                ? ProgramCounterDirection.Right
                                : ProgramCounterDirection.Left;
                        break;

                    case VerticalIfToken t:
                        a = stack.PopOrZero();
                        currentDirection = a == 0
                                ? ProgramCounterDirection.Down
                                : ProgramCounterDirection.Up;
                        break;

                    case QuoteToken t:
                        stringMode = !stringMode;
                        break;

                    case DuplicateToken t:
                        stack.Push(stack.PeekOrZero());
                        break;

                    case SwapToken t:
                        (a, b) = (stack.PopOrZero(), stack.PopOrZero());
                        stack.Push(a);
                        stack.Push(b);
                        break;

                    case PopToken t:
                        stack.PopOrZero();
                        break;

                    case OutputIntToken t:
                        Console.Write(stack.PopOrZero());
                        break;

                    case OutputCharToken t:
                        Console.Write(char.ConvertFromUtf32((int)stack.PopOrZero()));
                        break;

                    case JumpToken t:
                        playField.ProgramCounter.Move(currentDirection);
                        break;

                    case GetToken t:
                        (a, b) = (stack.PopOrZero(), stack.PopOrZero());
                        stack.Push(
                            playField.IsLegalPosition(a, b)
                                    ? playField[a, b].AsCharToken().AsciiValue
                                    : 0
                            );
                        break;

                    case PutToken t:
                        long c;
                        (a, b, c) = (stack.PopOrZero(), stack.PopOrZero(), stack.PopOrZero());
                        char val = (char)c;
                        playField[a, b] = new CharToken(val, a, b);
                        break;

                    case InputIntToken t:
                        stack.Push(PromptForInt("Input a number"));
                        break;

                    case InputCharToken t:
                        stack.Push(PromptForChar("Input a character"));
                        break;

                    case NumberToken t:
                        stack.Push(t.Value);
                        break;

                    case BlankToken t:
                        break;

                    case HaltToken t:
                        return;

                    default:
                        throw new TokenizerException($"Unknown token: {playField.Current}");
                    }
                }
                playField.ProgramCounter.Move(currentDirection);
            }
        }