import java.util.function.IntConsumer;

import java.util.*;

public class GameEngine
{
    public GameEngine (Vector<String> instructions, boolean debug)
    {
        _computer = new Intcode(instructions, INITIAL_INPUT, debug);
        _debug = debug;
        _theScreen = new Screen(_debug);
        _paddlePosition = null;
        _ballPosition = null;
        _stick = new Joystick();
    }

    public final boolean playGame ()
    {
        /*
         * Initialise the screen. Run the game instructions
         * once.
         */

         // Replace entry 0 with 2 (unlimited lives)

        _computer.changeInstruction(0, "2");

        int[] output = getOutput(INITIAL_INPUT);

        if (_debug)
            System.out.println("Tile information: <"+output[0]+", "+output[1]+"> and "+TileId.idToString(output[2]));

        System.out.println("**initial "+output[0]+" "+output[1]+" "+output[2]);

        Tile theTile = new Tile(new Coordinate(output[0], output[1]), output[2]);

        _theScreen.updateTile(theTile);

        if(theTile.getId() == TileId.BALL)
            _ballPosition = theTile.getPosition();
        else
        {
            if (theTile.getId() == TileId.PADDLE)
                _paddlePosition = theTile.getPosition();
        }

        /*
         * Where is the joystick?
         */

        if (_ballPosition.getX() > _paddlePosition.getX())
            _stick.setPosition(Joystick.TILTED_RIGHT);
        else
        {
            if (_ballPosition.getX() < _paddlePosition.getX())
                _stick.setPosition(Joystick.TILTED_LEFT);
        }

        System.out.println("**initial joystick "+_stick);

        /*
         * Now let's play the game!
         */

        System.out.println("\n\nPLAYING");

        //_computer = new Intcode(instructions, INITIAL_INPUT, debug);

        while (!_computer.hasHalted())
        {
            output = getOutput(Integer.toString(_stick.getPosition()));

            if (_debug)
                System.out.println("Tile information: <"+output[0]+", "+output[1]+"> and "+TileId.idToString(output[2]));

            System.out.println("**gaming values "+output[0]+" "+output[1]+" "+output[2]);

            if ((output[0] == -1) && (output[1] == 0))
            {
                // update score

                _theScreen.getSegmentDisplay().setScore(output[2]);

                System.out.println("**score now "+_theScreen.getSegmentDisplay());
            }
            else
            {
                theTile = new Tile(new Coordinate(output[0], output[1]), output[2]);

                _theScreen.updateTile(theTile);

                if(theTile.getId() == TileId.BALL)
                {
                    _ballPosition = theTile.getPosition();

                    if (_ballPosition.getX() > _paddlePosition.getX())
                        _stick.setPosition(Joystick.TILTED_RIGHT);
                    else
                    {
                        if (_ballPosition.getX() < _paddlePosition.getX())
                            _stick.setPosition(Joystick.TILTED_LEFT);
                        else
                            _stick.setPosition(Joystick.NEUTRAL_POSITION);
                    }

                    System.out.println("**gaming joystick "+_stick);
                }
                else
                {
                    if (theTile.getId() == TileId.PADDLE)
                        _paddlePosition = theTile.getPosition();
                }
            }
        }

        System.out.println("**score "+_theScreen.getSegmentDisplay());

        return true;
    }

    public final int getNumberOfBlocks ()
    {
        return _theScreen.numberOfBlocks();
    }

    private final int[] getOutput (String input)
    {
        int[] values = new int[3];

        while (!_computer.hasPaused() && !_computer.hasOutput())
        {
            _computer.singleStepExecution(input);
        }

        if (!_computer.hasPaused())
        {
            values[0] = Integer.parseInt(_computer.getOutput());

            while (!_computer.hasPaused() && !_computer.hasOutput())
            {
                _computer.singleStepExecution(input);
            }

            if (!_computer.hasPaused())
            {
                values[1] = Integer.parseInt(_computer.getOutput());

                while (!_computer.hasPaused() && !_computer.hasOutput())
                {
                    _computer.singleStepExecution(input);
                }

                values[2] = Integer.parseInt(_computer.getOutput());
            }
            else
            {
                System.out.println("Error - computer halted after outputing x value!");
            }
        }

        return values;
    }

    private Intcode _computer;
    private boolean _debug;
    private Screen _theScreen;
    private Coordinate _paddlePosition;
    private Coordinate _ballPosition;
    private Joystick _stick;

    private static final String INITIAL_INPUT = "0"; // nothing specified in the overview
}
@@ -424,32 +424,78 @@
 ayGame ()%0A    %7B%0A
+        int%5B%5D output = null;%0A                %0A
         /*%0A     
@@ -679,37 +679,90 @@
  %222%22);%0A%0A        
-int%5B%5D
+while (!_computer.waitingForInput())%0A        %7B%0A           
  output = getOut
@@ -782,32 +782,36 @@
 NPUT);%0A%0A        
+ 
+   
 if (_debug)%0A    
@@ -798,32 +798,36 @@
     if (_debug)%0A
+    
             Syst
@@ -929,32 +929,36 @@
 %5B2%5D));%0A%0A        
+    
 System.out.print
@@ -1006,32 +1006,36 @@
  %22+output%5B2%5D);%0A%0A
+    
         Tile the
@@ -1101,32 +1101,36 @@
 t%5B2%5D);%0A%0A        
+    
 _theScreen.updat
@@ -1146,34 +1146,39 @@
 Tile);%0A%0A        
+   
+ 
 if
+ 
 (theTile.getId()
@@ -1186,32 +1186,36 @@
 == TileId.BALL)%0A
+    
             _bal
@@ -1249,32 +1249,36 @@
 tion();%0A        
+ 
+   
 else%0A        %7B%0A 
@@ -1266,34 +1266,42 @@
    else%0A        
-%7B%0A
+    %7B%0A    
             if (
@@ -1326,32 +1326,36 @@
  TileId.PADDLE)%0A
+    
                 
@@ -1387,32 +1387,46 @@
 .getPosition();%0A
+            %7D%0A
         %7D%0A%0A     
@@ -2657,16 +2657,21 @@
         
+Tile 
 theTile 
@@ -5148,11 +5148,12 @@
 T = 
-%220%22
+null
 ; //

Update GameEngine.java