text: jsPsych.plugins["Battleships_replay_2players"] = (function() {
  
      var plugin = {};
  
      plugin.info = {
          name: 'Battleships_replay_2players',
  
          parameters: {
              grid: {
                  type: jsPsych.plugins.parameterType.INT,
                  pretty_name: "Grid",
                  default: [
                      ['0', '0', '0', '0', '0'],
                      ['A', 'A', 'A', '0', '0'],
                      ['0', '0', '0', '0', '0'],
                      ['0', '0', '0', 'B', '0'],
                      ['C', 'C', '0', 'B', '0']
                  ],
                  description: "Grid. 0 means water, everything else is a ship."
              },
              end_screen_time: {
                  type: jsPsych.plugins.parameterType.INT,
                  pretty_name: 'end screen time',
                  default: 2000,
                  description: 'For how many milliseconds is the end screen presented?'
              },
              text: {
                  type: jsPsych.plugins.parameterType.STRING,
                  pretty_name: 'text',
                  default: `To win, you need to sink one 3-square submarine
  and two 2-square patrol boats.`,
                  description: 'Text to display on top of grid.'
              },
              description: {
                  type: jsPsych.plugins.parameterType.STRING,
                  pretty_name: 'description',
                  default: {
                      right: `Replaying player 2's game:`,
                      left: `Replaying Player 1's game`
                  },
                  description: 'Description'
              },
              click_log: {
                  type: jsPsych.plugins.parameterType.OBJECT,
                  pretty_name: 'click_log',
                  default: {
                      'right': {
                          "i": [1, 2, 3, 1, 1, 2, 2, 3, 2, 3, 3, 4, 4, 4],
                          "j": [0, 0, 0, 1, 2, 3, 4, 4, 2, 3, 2, 3, 1, 0],
                          "t": [3559, 3906, 4284, 5152, 6111, 7086, 7696, 7993, 8532, 9145, 9580, 10129, 11173.5, 11552],
                          "hit": ["A", "0", "0", "A", "A", "0", "0", "0", "0", "B", "0", "B", "C", "C"]
                      },
                      "left": {
                          "i": [1, 2, 1, 2, 1, 0, 1, 3, 3, 4, 4, 4, 4],
                          "j": [3, 3, 2, 2, 1, 2, 0, 2, 3, 3, 2, 1, 0],
                          "t": [1439, 1932.5, 4361, 4998, 5583, 6664, 7382, 8805, 9230, 10242, 11254.5, 12390, 13410],
                          "hit": ["0", "0", "A", "0", "A", "0", "A", "0", "B", "B", "0", "C", "C"]
                      }
                  },
                  description: 'Click log'
              },
              pause_before_first_click: {
                type: jsPsych.plugins.parameterType.INT,
                pretty_name: 'pause before first click',
                default: undefined,
                description: `Time between clicking the play button and the first
                click playing, in seconds. if undefined, use whatever time it took
                the subject to actually click the first click.`
              },
            click_on_pretender: {
              type: jsPsych.plugins.parameterType.BOOL,
              pretty_name: 'click on pretender',
              default: true,
              description: `If true, participant clicks on who they think had hints.
              if false, on who had no hints.`
            }
          }
      }
  
      plugin.trial = function(display_element, trial) {
  
        console.log(trial.click_on_pretender)
  
          display_element.innerHTML = '';
  
          //open a p5 sketch
          let sketch = function(p) {
  
              const du = p.min([window.innerWidth, window.innerHeight]) * 2 / 5 //drawing unit
              const left_margin = p.round((window.innerWidth - window.innerHeight) / 2);
              const top_margin = p.round((window.innerHeight - du) * 2 / 5);
              const square_size = Math.floor(du / trial.grid.length);
              const colors = {
                  'sea': p.color(100, 155, 200),
                  'unknown': p.color(255, 230, 166),
                  'ship': p.color(200, 50, 55)
              }
              var grid_state = trial.grid.map(([...rest]) => rest.map(x => 'unknown'));
              const num_nonzero = trial.grid.flat().reduce((a, b) => a + (b == '0' ? 0 : 1), 0);
              var hits = 0;;
              var last_click_time = p.millis()
              var click_number = 0;
              var replay_log = [];
              var playing_side = 'waiting_for_input';
              var starting_time = p.millis();
              var played_left = false;
              var played_right = false;
  
              // if pause_before_first_click is defined, start the first click then.
              if (trial.pause_before_first_click != undefined) {
                var first_click_timing_right = trial.click_log.right.t[0];
                trial.click_log.right.t = trial.click_log.right.t.map(
                  x=>x-first_click_timing_right+trial.pause_before_first_click
                );
  
                var first_click_timing_left = trial.click_log.left.t[0];
                trial.click_log.left.t = trial.click_log.left.t.map(
                  x=>x-first_click_timing_left+trial.pause_before_first_click
                )
              }
  
              trial.click_log.right.t.push(Infinity);
              trial.click_log.left.t.push(Infinity);
  
              function grid_coordinates_to_screen_coordinates(i, j, which_grid) {
  
                  if (which_grid == 'left') {
                      x = left_margin + j * square_size + Math.round(square_size / 2);
                      y = top_margin + i * square_size + Math.round(square_size / 2);
                  } else if (which_grid == 'right') {
                      x = left_margin + du * 1.5 + j * square_size + Math.round(square_size / 2);
                      y = top_margin + i * square_size + Math.round(square_size / 2);
                  } else if (which_grid == 'center') {
                      x = p.round(window.innerWidth / 2 - du / 4) + j * square_size / 2 + Math.round(square_size / 4);
                      y = i * square_size / 2 + Math.round(square_size / 4);
                  }
                  return ({
                      x: x,
                      y: y
                  })
              }
  
              // function screen_coordinates_to_grid_coordinates(x,y) {
              // 	i = Math.floor((y-top_margin)/square_size);
              // 	j = Math.floor((x-left_margin)/square_size);
              // 	return({i:i,j:j})
              // }
  
              function msToTime(duration) {
                  var milliseconds = Math.floor((duration % 1000) / 10),
                      seconds = Math.floor((duration / 1000) % 60),
                      minutes = Math.floor((duration / (1000 * 60)) % 60),
                      hours = Math.floor((duration / (1000 * 60 * 60)) % 24);
  
                  hours = (hours < 10) ? "0" + hours : hours;
                  minutes = (minutes < 10) ? "0" + minutes : minutes;
                  seconds = (seconds < 10) ? "0" + seconds : seconds;
                  milliseconds = (milliseconds < 10) ? "0" + milliseconds : milliseconds;
                  return hours + ":" + minutes + ":" + seconds + ":" + milliseconds;
              }
  
              p.preload = function() {
                  img = p.loadImage('assets/hit.png');
              }
  
              //sketch setup
              p.setup = function() {
  
                  p.createCanvas(p.windowWidth, p.windowHeight);
                  p.strokeWeight(0);
                  p.frameRate(trial.frame_rate);
                  p.rectMode(p.CENTER)
                  p.imageMode(p.CENTER)
              }
  
              //organize everything in one sequence
              p.draw = function() {
  
                  p.background(255);
  
                  // Display true positions
                  for (var i = 0; i < trial.grid.length; i++) {
                      for (var j = 0; j < trial.grid.length; j++) {
                          xy = grid_coordinates_to_screen_coordinates(i, j, 'center');
                          p.fill(trial.grid[i][j] == '0' ? colors['sea'] : colors['ship']);
                          p.stroke(255);
                          p.strokeWeight(1)
                          p.square(xy.x, xy.y, square_size / 2);
                      }
                  }
  
                  // emulate clicks
                  if (playing_side != 'waiting_for_input') {
                      if (p.millis() - starting_time >= trial.click_log[playing_side].t[click_number]) {
                          ij = {
                              i: trial.click_log[playing_side].i[click_number],
                              j: trial.click_log[playing_side].j[click_number]
                          };
                          if (trial.grid[ij.i][ij.j] == '0') {
                              grid_state[ij.i][ij.j] = 'sea'
                          } else {
                              grid_state[ij.i][ij.j] = 'ship';
                              hits += 1;
                          }
                          last_click_time = p.millis();
                          click_number = click_number + 1
                      }
                  }
  
                  // Description
                  if (playing_side != 'waiting_for_input') {
                      p.push()
                      p.textFont("monospace", 15)
                      text = trial.description[playing_side] + ' ' + msToTime(p.millis() - starting_time);
                      p.textAlign(p.Left, p.TOP)
                      p.fill(100);
                      p.strokeWeight(0)
                      p.text(text, playing_side == 'left' ? left_margin : left_margin + du * 1.5, top_margin + du + 20)
                      p.pop()
                  }
  
                  for (var i = 0; i < trial.grid.length; i++) {
                      for (var j = 0; j < trial.grid.length; j++) {
  
                          xy = grid_coordinates_to_screen_coordinates(i, j, 'left');
                          p.fill(playing_side == 'left' ? colors[grid_state[i][j]] : colors['unknown']);
                          p.stroke(127, 182, 177);
                          p.strokeWeight(1)
                          p.square(xy.x, xy.y, square_size);
                          if (playing_side == 'left' & grid_state[i][j] == 'ship') {
                              mark_hit(xy.x, xy.y, square_size / 2)
                          }
  
                          xy = grid_coordinates_to_screen_coordinates(i, j, 'right');
                          p.fill(playing_side == 'right' ? colors[grid_state[i][j]] : colors['unknown']);
                          p.stroke(127, 182, 177);
                          p.strokeWeight(1)
                          p.square(xy.x, xy.y, square_size);
                          if (playing_side == 'right' & grid_state[i][j] == 'ship') {
                              mark_hit(xy.x, xy.y, square_size / 2)
                          }
  
                      }
                  }
  
                  if (hits < num_nonzero) {
                      // 					var text =
                      // `You clicked on ${click_log.t.length} squares.
                      // ${trial.text}`
                      // 					p.textSize(15)
                      // 					p.push()
                      // 					p.textAlign(p.Left, p.TOP)
                      // 					p.fill(0);
                      // 					p.strokeWeight(0)
                      // 					// p.text(text,left_margin,top_margin-70)
                      // 					p.pop()
                  } else if (p.millis() - last_click_time < trial.end_screen_time) {
                      for (var i = 0; i < trial.grid.length; i++) {
                          for (var j = 0; j < trial.grid.length; j++) {
                              if (trial.grid[i][j] != '0') {
                                  xy = grid_coordinates_to_screen_coordinates(i, j, playing_side);
                                  water_height = square_size *
                                      (p.millis() - last_click_time) / trial.end_screen_time;
                                  p.push()
                                  p.rectMode(p.CORNERS)
                                  p.fill(colors['sea'])
                                  p.rect(xy.x - square_size / 2,
                                      xy.y + square_size / 2 - water_height,
                                      xy.x + square_size / 2,
                                      xy.y + square_size / 2);
                                  p.pop()
                              }
                          }
                      }
                  } else if (playing_side != 'waiting_for_input') {
                      for (var i = 0; i < trial.grid.length; i++) {
                          for (var j = 0; j < trial.grid.length; j++) {
                              if (trial.grid[i][j] != '0') {
                                  xy = grid_coordinates_to_screen_coordinates(i, j, playing_side);
                                  water_height = square_size *
                                      (p.millis() - last_click_time) / trial.end_screen_time;
                                  p.push()
                                  p.rectMode(p.CORNERS)
                                  p.fill(colors['sea'])
                                  p.rect(xy.x - square_size / 2,
                                      xy.y + square_size / 2 - water_height,
                                      xy.x + square_size / 2,
                                      xy.y + square_size / 2);
                                  p.pop()
                              }
                          }
                      }
                      if (playing_side == 'right') {
                          played_right = true;
                      } else if (playing_side == 'left') {
                          played_left = true;
                      }
                      playing_side = 'waiting_for_input';
                  }
  
                  var text =
                      `Press 1 to see the game of the left player, or 2 to see the game of the right player.
  ${(played_right & played_left)? `When you are ready to decide, click on the board of the player ${trial.click_on_pretender? 'who had hints' : 'who had no hints'}.` : ''}`
                  p.textSize(20)
                  p.push()
                  p.textAlign(p.CENTER, p.TOP)
                  p.fill(0);
                  p.strokeWeight(0)
                  p.text(text, window.innerWidth / 2, top_margin + du + 50)
                  p.pop();
  
                  if (played_left & played_right &
                      p.mouseY > top_margin & p.mouseY < top_margin + du) {
                        if (p.mouseX > left_margin & p.mouseX < left_margin + du) {
                          var xposition = left_margin+du/2;
                        } else if (p.mouseX > left_margin + du * 1.5 & p.mouseX < left_margin + du * 2.5) {
                          var xposition = left_margin + du * 2;
                        } else {
                          var xposition = undefined;
                        }
                      if (xposition !=undefined) {
                        p.push();
                        p.fill(255,255,255,128);
                        p.stroke(0);
                        p.strokeWeight(4);
                        p.rect(xposition, top_margin+du/2, du, du);
                        p.pop()
                        p.push()
                        p.textAlign(p.CENTER, p.CENTER)
                        p.fill(0);
                        p.strokeWeight(0)
                        p.textSize(40);
                        p.text(trial.click_on_pretender? 'I think this player had hints' : 'I think this player had no hints',
                        xposition, top_margin+du/2, du, du)
                        p.pop();
                      }
                  }
              }
  
              mark_hit = function(x, y, size) {
                  p.image(img, x, y, size, size);
              }
  
              p.keyPressed = function() {
                  if ((p.keyCode == 49 | p.keyCode==97) & playing_side == 'waiting_for_input') {
                      playing_side = 'left';
                      starting_time = p.millis();
                      hits = 0;
                      last_click_time = p.millis()
                      click_number = 0;
                      replay_log.push('left')
                      grid_state = trial.grid.map(([...rest]) => rest.map(x => 'unknown'));
                  } else if ((p.keyCode == 50 | p.keyCode==98) & playing_side == 'waiting_for_input') {
                      playing_side = 'right';
                      starting_time = p.millis();
                      hits = 0;;
                      last_click_time = p.millis()
                      click_number = 0;
                      replay_log.push('right')
                      grid_state = trial.grid.map(([...rest]) => rest.map(x => 'unknown'));
                  }
              };
  
  
  
              p.mouseClicked = function() {
                  if (played_left & played_right &
                      p.mouseY > top_margin & p.mouseY < top_margin + du) {
                      if (p.mouseX > left_margin & p.mouseX < left_margin + du) {
                        // regardless of whether the participant is asked to click
                        // on the board of the player who had or had no hints, the
                        // decision is recorded as the player who was believed
                        // to have had hints.
                          decision = trial.click_on_pretender? 'left' : 'right';
                          p.remove()
                          // data saving
                          var trial_data = {
                              grid: trial.grid,
                              replay_log: replay_log,
                              decision: decision
                          };
                          // end trial
                          jsPsych.finishTrial(trial_data);
                      } else if (p.mouseX > left_margin + du * 1.5 & p.mouseX < left_margin + du * 2.5) {
                        // regardless of whether the participant is asked to click
                        // on the board of the player who had or had no hints, the
                        // decision is recorded as the player who was believed
                        // to have had hints.
                          decision = trial.click_on_pretender? 'right' : 'left';
                          p.remove()
                          // data saving
                          var trial_data = {
                              grid: trial.grid,
                              replay_log: replay_log,
                              decision: decision
                          };
                          console.log(trial_data)
                          // end trial
                          jsPsych.finishTrial(trial_data);
                      }
                  }
              }
          };
  
          // start sketch!
          let myp5 = new p5(sketch);
  
      }
  
      //Return the plugin object which contains the trial
      return plugin;
  })();
  