Example #1
0
        public void DropItem(string item)
        {
            // Provide input for the program
            if (IntcodeProgramStatus.AwaitingInput.Equals(_programStatus))
            {
                _inputProviderAutomated.AddInputValue("drop " + item);
                _inputProviderAutomated.AddInputValue(10);
            }

            // Run a loop of the program
            _programStatus = _computer.RunProgram();

            // Process program output
            // Assumption: If there is new output, then the robot has
            // entered a room corresponding to the next robot position
            if (_outputIndex < _outputListener.Values.Count)
            {
                int numberOfNewOutputValues = _outputListener.Values.Count - _outputIndex;
                var latestOutput            = string.Join("", _outputListener.Values
                                                          .GetRange(_outputIndex, numberOfNewOutputValues)
                                                          .Select(v => char.ConvertFromUtf32((int)v)));
                _outputIndex += numberOfNewOutputValues;

                var robotOutputResult = RobotOutputHelper.ProcessRobotOutput(latestOutput);
                if (!RobotOutputType.DroppedItem.Equals(robotOutputResult.Type) &&
                    IsAutomated)
                {
                    throw new Exception("Failed to drop the item");
                }

                RobotInventory.Remove(item);
                ExploredPoints[RobotPosition].Items.Add(item);
                ItemLocations.Add(item, RobotPosition);
            }

            _programLoopCount++;
        }
        public IntcodeProgramStatus RunProgram()
        {
            IntcodeProgramStatus status = IntcodeProgramStatus.Running;

            while (true)
            {
                LogDebugMessage($"Pos: {_position.ToString("0000")}, Cmd: {_program[_position]}");
                var parsedCommand = ParseCommand(_program[_position]);
                var opcode        = parsedCommand[0];
                if (opcode == 1)
                {
                    // Add param1 + param2, store in address pointed to by param3
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2 = GetParameterValue(_position + 2, 2, parsedCommand);
                    var val3 = GetParameterWritePosition(_position + 3, 3, parsedCommand);
                    SetMemoryValue(val3, val1 + val2);
                    _position += 4;
                }
                else if (opcode == 2)
                {
                    // Multiply param1 * param2, store in address pointed to by param3
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2 = GetParameterValue(_position + 2, 2, parsedCommand);
                    var val3 = GetParameterWritePosition(_position + 3, 3, parsedCommand);
                    SetMemoryValue(val3, val1 * val2);
                    _position += 4;
                }
                else if (opcode == 3)
                {
                    // Take user input, and store in the parameter location
                    // If the input provider doesn't have any input,
                    // then pause the program and return awaiting input status
                    if (!_inputProvider.HasInput())
                    {
                        status = IntcodeProgramStatus.AwaitingInput;
                        break;
                    }
                    BigInteger input = _inputProvider.GetInput();
                    var        val1  = GetParameterWritePosition(_position + 1, 1, parsedCommand);
                    SetMemoryValue(val1, input);
                    _position += 2;
                }
                else if (opcode == 4)
                {
                    // Output a value
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    _outputListener.SendOutput(val1);
                    _position += 2;
                }
                else if (opcode == 5)
                {
                    // Opcode 5 is jump-if-true: if the first parameter is
                    // non-zero, it sets the instruction pointer to the value
                    // from the second parameter. Otherwise, it does nothing.
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2 = GetParameterValue(_position + 2, 2, parsedCommand);
                    if (val1 != 0)
                    {
                        _position = GetMemoryAddress(val2);
                    }
                    else
                    {
                        _position += 3;
                    }
                }
                else if (opcode == 6)
                {
                    // Opcode 6 is jump-if-false: if the first parameter is
                    // zero, it sets the instruction pointer to the value from
                    // the second parameter. Otherwise, it does nothing.
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2 = GetParameterValue(_position + 2, 2, parsedCommand);
                    if (val1 == 0)
                    {
                        _position = GetMemoryAddress(val2);
                    }
                    else
                    {
                        _position += 3;
                    }
                }
                else if (opcode == 7)
                {
                    // Opcode 7 is less than: if the first parameter is less
                    // than the second parameter, it stores 1 in the position
                    // given by the third parameter.
                    // Otherwise, it stores 0.
                    var val1       = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2       = GetParameterValue(_position + 2, 2, parsedCommand);
                    var val3       = GetParameterWritePosition(_position + 3, 3, parsedCommand);
                    var valToStore = val1 < val2 ? 1 : 0;
                    SetMemoryValue(val3, valToStore);
                    _position += 4;
                }
                else if (opcode == 8)
                {
                    // Opcode 8 is equals: if the first parameter is equal to
                    // the second parameter, it stores 1 in the position given
                    // by the third parameter.
                    // Otherwise, it stores 0.
                    var val1       = GetParameterValue(_position + 1, 1, parsedCommand);
                    var val2       = GetParameterValue(_position + 2, 2, parsedCommand);
                    var val3       = GetParameterWritePosition(_position + 3, 3, parsedCommand);
                    var valToStore = val1 == val2 ? 1 : 0;
                    SetMemoryValue(val3, valToStore);
                    _position += 4;
                }
                else if (opcode == 9)
                {
                    // Opcode 9 adjusts the relative base by the value of its
                    // only parameter. The relative base increases (or
                    // decreases, if the value is negative) by the value of the
                    // parameter.
                    // For example, if the relative base is 2000, then after
                    // the instruction 109,19, the relative base would be 2019.
                    // If the next instruction were 204,-34, then the value at
                    // address 1985 would be output.
                    var val1 = GetParameterValue(_position + 1, 1, parsedCommand);
                    _relativeBase += GetMemoryAddress(val1);
                    _position     += 2;
                }
                else if (opcode == 99)
                {
                    status = IntcodeProgramStatus.Completed;
                    break;
                }
                else if (opcode != 99)
                {
                    throw new Exception($"Invalid opcode {_program[_position]} at position {_position}");
                }
            }
            return(status);
        }
Example #3
0
        public void Explore()
        {
            // Initialize the exploration variables
            string targetUnexploredPoint = RobotPosition;
            var    movementCommandsToTargetUnexploredPoint = new Queue <string>();
            string nextRobotPosition = RobotPosition;

            // Continue exploring while points remain unexplored
            while (ExplorationTree.Count > 0)
            {
                // Run a loop of the program
                _programStatus = _computer.RunProgram();

                // Process program output
                // Assumption: If there is new output, then the robot has
                // entered a room corresponding to the next robot position
                if (_outputIndex < _outputListener.Values.Count)
                {
                    int numberOfNewOutputValues = _outputListener.Values.Count - _outputIndex;
                    var latestOutput            = string.Join("", _outputListener.Values
                                                              .GetRange(_outputIndex, numberOfNewOutputValues)
                                                              .Select(v => char.ConvertFromUtf32((int)v)));
                    _outputIndex += numberOfNewOutputValues;
                    if (!IsAutomated)
                    {
                        Console.WriteLine(latestOutput);
                    }

                    var robotOutputResult = RobotOutputHelper.ProcessRobotOutput(latestOutput);
                    if (!RobotOutputType.MovedToPoint.Equals(robotOutputResult.Type) &&
                        !RobotOutputType.EjectedBack.Equals(robotOutputResult.Type) &&
                        IsAutomated)
                    {
                        throw new Exception("While exploring in automated mode, we should only either move into spaces or get ejected back by the security system");
                    }

                    // Add this point to the set of explored points
                    if (robotOutputResult.ShipSectionInfo != null)
                    {
                        if (!ExploredPoints.ContainsKey(nextRobotPosition))
                        {
                            ExploredPoints.Add(nextRobotPosition, robotOutputResult.ShipSectionInfo);
                        }
                        ExploredPoints[nextRobotPosition] = robotOutputResult.ShipSectionInfo;

                        // Remove this point from the set of unxplored points
                        if (UnexploredPoints.Contains(nextRobotPosition))
                        {
                            UnexploredPoints.Remove(nextRobotPosition);
                        }
                    }

                    // Reset the target unexplored point if we've reached it
                    if (nextRobotPosition.Equals(targetUnexploredPoint))
                    {
                        targetUnexploredPoint = null;
                    }

                    // Only move the robot if they actually moved
                    if (RobotOutputType.MovedToPoint.Equals(robotOutputResult.Type))
                    {
                        RobotPosition = nextRobotPosition;
                    }
                    else if (RobotOutputType.EjectedBack.Equals(robotOutputResult.Type))
                    {
                        WeightFloor = nextRobotPosition;
                        RallyPoint  = RobotPosition;
                    }

                    // Add any new unexplored points
                    var newUnexploredPoints = GetNewUnexploredPoints();
                    ExplorationTree.Add(newUnexploredPoints, RobotPosition);
                    foreach (var p in newUnexploredPoints)
                    {
                        UnexploredPoints.Add(p);
                    }
                }

                // Provide input for the program
                if (IntcodeProgramStatus.AwaitingInput.Equals(_programStatus))
                {
                    if (!IsAutomated)
                    {
                        DrawMap();
                        var userInput = _inputProviderManual.AddInput(appendNewLine: true).Trim();
                        var isValidMovementCommand = RobotMovementHelper.GetIsValidMovementCommand(userInput);
                        if (isValidMovementCommand)
                        {
                            nextRobotPosition = RobotMovementHelper.Move(RobotPosition, userInput);
                        }
                        targetUnexploredPoint = GetNextTargetUnexploredPoint(
                            currentTargetUnexploredPoint: RobotPosition);
                    }
                    else
                    {
                        if (targetUnexploredPoint != null &&
                            movementCommandsToTargetUnexploredPoint.Count == 0)
                        {
                            throw new Exception("Ran out of movement commands before reaching target");
                        }

                        // Acquire a new target unexplored point if necessary
                        // If the target unexplored point is null, then the
                        // robot reached the previous target
                        // If the next target unexplored point is null, then
                        // we've finished exploring
                        if (targetUnexploredPoint == null)
                        {
                            targetUnexploredPoint = GetNextTargetUnexploredPoint(
                                currentTargetUnexploredPoint: RobotPosition);
                            if (targetUnexploredPoint != null)
                            {
                                var pathToTarget = GetPathToPoint(
                                    startPoint: RobotPosition,
                                    targetPoint: targetUnexploredPoint);
                                if (pathToTarget.Path.Count == 0)
                                {
                                    throw new Exception("Path not found");
                                }
                                movementCommandsToTargetUnexploredPoint = GetMovementCommandsForPath(
                                    path: pathToTarget.Path);
                            }
                        }

                        // If the target is null, then we finished exploring
                        // Otherwise, input the new movement command
                        // and update the next robot position
                        if (targetUnexploredPoint != null)
                        {
                            if (movementCommandsToTargetUnexploredPoint.Count == 0)
                            {
                                throw new Exception("Failed to properly acquire new target path");
                            }

                            string movementCommand = movementCommandsToTargetUnexploredPoint.Dequeue();
                            _inputProviderAutomated.AddInputValue(movementCommand);
                            _inputProviderAutomated.AddInputValue(10);
                            nextRobotPosition = RobotMovementHelper.Move(RobotPosition, movementCommand);
                        }
                    }
                }

                _programLoopCount++;
            }

            // Exploration complete, populate item lists
            InitializeItemTrackers();
        }
Example #4
0
        public RobotOutputResult MoveRobotToPoint(string targetPoint)
        {
            if (!IsAutomated)
            {
                throw new Exception("This should only be done in automated mode");
            }

            RobotOutputResult result = null;

            // Initialize the movement variables
            var path = GetPathToPoint(RobotPosition, targetPoint);

            if (path.Path.Count == 0)
            {
                throw new Exception("Path not found");
            }
            var    movementCommands  = GetMovementCommandsForPath(path.Path);
            string nextRobotPosition = RobotPosition;

            // Continue looping until the robot reaches the target
            while (!RobotPosition.Equals(targetPoint))
            {
                // Run a loop of the program
                _programStatus = _computer.RunProgram();

                // Process program output
                // Assumption: If there is new output, then the robot has
                // entered a room corresponding to the next robot position
                if (_outputIndex < _outputListener.Values.Count)
                {
                    int numberOfNewOutputValues = _outputListener.Values.Count - _outputIndex;
                    var latestOutput            = string.Join("", _outputListener.Values
                                                              .GetRange(_outputIndex, numberOfNewOutputValues)
                                                              .Select(v => char.ConvertFromUtf32((int)v)));
                    _outputIndex += numberOfNewOutputValues;

                    var robotOutputResult = RobotOutputHelper.ProcessRobotOutput(latestOutput);
                    if (!RobotOutputType.MovedToPoint.Equals(robotOutputResult.Type) &&
                        !RobotOutputType.EjectedBack.Equals(robotOutputResult.Type) &&
                        IsAutomated)
                    {
                        throw new Exception("While exploring in automated mode, we should only either move into spaces or get ejected back by the security system");
                    }

                    // Update the set of explored points
                    if (robotOutputResult.ShipSectionInfo != null)
                    {
                        if (!ExploredPoints.ContainsKey(nextRobotPosition))
                        {
                            ExploredPoints.Add(nextRobotPosition, robotOutputResult.ShipSectionInfo);
                        }
                        ExploredPoints[nextRobotPosition] = robotOutputResult.ShipSectionInfo;

                        // Remove this point from the set of unxplored points
                        if (UnexploredPoints.Contains(nextRobotPosition))
                        {
                            UnexploredPoints.Remove(nextRobotPosition);
                        }
                    }

                    // Only move the robot if they actually moved
                    if (RobotOutputType.MovedToPoint.Equals(robotOutputResult.Type))
                    {
                        RobotPosition = nextRobotPosition;
                    }
                    else if (RobotOutputType.EjectedBack.Equals(robotOutputResult.Type))
                    {
                        RallyPoint = RobotPosition;
                        result     = robotOutputResult;
                        break;
                    }

                    if (RobotPosition.Equals(targetPoint))
                    {
                        result = robotOutputResult;
                        break;
                    }
                }

                // Provide input for the program
                if (IntcodeProgramStatus.AwaitingInput.Equals(_programStatus))
                {
                    if (movementCommands.Count == 0 &&
                        !RobotPosition.Equals(targetPoint))
                    {
                        throw new Exception("Ran out of commands before robot reached target");
                    }

                    string movementCommand = movementCommands.Dequeue();
                    _inputProviderAutomated.AddInputValue(movementCommand);
                    _inputProviderAutomated.AddInputValue(10);
                    nextRobotPosition = RobotMovementHelper.Move(RobotPosition, movementCommand);
                }

                _programLoopCount++;
            }
            return(result);
        }