> For the complete documentation index, see [llms.txt](https://alfredo-reyes-montero.gitbook.io/tensorflow-javascript/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alfredo-reyes-montero.gitbook.io/tensorflow-javascript/application/pingpong-ai/code.md).

# Code

First create a html file and name it pingpong.html

```
<div id='mainContent'></div>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.11.2"> </script>
<script src="pingpong.js"></script>
```

We could reuse a code of a pingpong and we can add AI by tensorflow js:

[js pong example tutorial](https://robots.thoughtbot.com/pong-clone-in-javascript)

Now we just need to add the pong game code. I am going to just go in order of the script itself. To begin, we want to defined our model:

```
// Model Definition
const model = tf.sequential();
model.add(tf.layers.dense({units: 256, inputShape: [8]})); //input is a 1x8
model.add(tf.layers.dense({units: 512, inputShape: [256], activation:"sigmoid"}));
model.add(tf.layers.dense({units: 256, inputShape: [512], activation:"sigmoid"}));
model.add(tf.layers.dense({units: 3, inputShape: [256]})); //returns a 1x3
const learningRate = 0.001;
const optimizer = tf.train.adam(learningRate);
model.compile({loss: 'meanSquaredError', optimizer: optimizer});
```

For this game of Pong, we're going to take in the following elements as input features:

1. Player paddle x
2. Computer paddle x
3. Ball x
4. Ball y
5. previous ball x
6. previous ball y
7. previous player paddle x
8. previous computer paddle x

Eventually, we'll have a model that outputs 3 things: Move left, do nothing, move right, which will translate to: \[1,0,0], \[0,1,0] or \[0,0,1]. We'll then find the argmax of that, and pass that as a -1, 0, or 1, so the above function moves at a multiple of 4 that many pixels. So, if the model outputs a \[1,0,0], the argmax is 0. To translate the argmax to a -1,0, or 1, we do -1. We subtract 1 from 0, getting -1.

Then -1 is passed to the ai\_update function, where -1 is multipleid by 4 to be -4, and the paddle is moved -4 pixels on the x-axis (4 pixels left).

Now, in order to train the AI, we need to be able to collect data, so we store it to variables:

```
function AI(){
    this.previous_data = null;
    this.training_data = [[], [], []];
    this.last_data_object = null;
    this.turn = 0;
    this.grab_data = true;
    this.flip_table = true;
}
```

Then save them to an array every frame:

```
// Custom code:
// Saved data per frame
AI.prototype.save_data = function(player, computer, ball){
    if(!this.grab_data)
        return;

    // First frame (no prior data):
    if(this.previous_data == null){
        data = this.flip_table ? [width - computer.x, width - player.x, width - ball.x, height - ball.y] : [player.x, computer.x, ball.x, ball.y];
        this.previous_data = data;
        return;
    }

    // table is rotated to learn from player, but apply to computer position:
    if(this.flip_table){
        data_xs = [width - computer.x, width - player.x, width - ball.x, height - ball.y];
        index = ((width - player.x) > this.previous_data[1])?0:(((width - player.x) == this.previous_data[1])?1:2);
    }else{
        data_xs = [player.x, computer.x, ball.x, ball.y];
        index = (player.x < this.previous_data[0])?0:((player.x == this.previous_data[0])?1:2);
    }

    this.last_data_object = [...this.previous_data, ...data_xs];
    this.training_data[index].push(this.last_data_object);
    this.previous_data = data_xs;
}
```

Deciding whether to play as ai

```
AI.prototype.new_turn = function(){
    this.previous_data = null;
    this.turn++;
    console.log('new turn: ' + this.turn);

    //hm games til train?
    if(this.turn > 1){
        this.train();
        computer.ai_plays = true;
        this.reset();
    }
}
```

And then code to make predictions:

```
// TensorFlow JS code:
AI.prototype.predict_move = function(){
    console.log('predicting');
    if(this.last_data_object != null){
        //use this.last_data_object for input data
        //do prediction here
        //return -1/0/1
        prediction = model.predict(tf.tensor([this.last_data_object]));
        return tf.argMax(prediction, 1).dataSync()-1;
    }

}
```
