Code viewer for World: tic tac toe2
let cols = 3; let rows = 3;
let size;
let board = Array.from({ length: cols }, () => Array(rows).fill(0));
let board2 = Array.from({ length: cols }, () => Array(rows).fill(0));
let players = ['X', 'O'];
let currentPlayer;
let currentPlayer2;
let gap = 50;
var COHERE_API_KEY = "kWWGEmvtADgXvs7n5JBmK9m0aaK56z26h5EmClq7";
var LLAMA_API_KEY = "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";
let chat_hist = [];
let chat_hist2 = [];

function setup() {
    initializeChat();
    initializeChatLlama();
    createCanvas(900, 900);
    size = (width- gap)/cols / 2;
    currentPlayer = players[floor(random(2))];
    currentPlayer2 = players[floor(random(2))];
}



function drawBoard(board, xOffset, yOffset){
    for(let i=0; i<cols; i++){
        for (let j=0; j<rows; j++){
            rect(i*size + xOffset, j*size + yOffset, size, size);
            if (board[i][j] !== 0){
            textAlign(CENTER, CENTER);
            textSize(30);
            text(
                board[i][j], 
                xOffset + i * size +  size / 2, 
                size/2 + yOffset + j*size);
            }
        }
    }

} 
function mousePressed() {
    let x = floor(mouseX/size);
    let y = floor(mouseY/size);
    
    if (mouseX < width / 2 - gap / 2) {
        placePieces(board, x, y, currentPlayer, "currentPlayer");
        let move = `${x} ${y}`;
        sendToCohere(move);
        
    }else if (mouseX > width / 2 + gap / 2) {
        placePieces(board2, x - cols, y, currentPlayer2, "currentPlayer2");
        let move = `${x} ${y}`;
        console.log(move);
        sendToLlama(move);
    }


}

function placePieces(b, x, y,player, playerName){
    if(x >= 0 && x < cols && y >= 0 && y < rows){
        if (b[x][y] == 0){
            b[x][y] = player;
            if (playerName === "currentPlayer"){
                if(currentPlayer == 'X'){
                currentPlayer = 'O';
                }else{
                    currentPlayer = 'X';
                }
            }
            else{
                if(currentPlayer2 == 'X'){
                    currentPlayer2 = 'O';
                }else{
                    currentPlayer2 = 'X';
                }
            }
        }
    }
         else{
            print("Spot not available");
        }
    
}

// Function to initialize the chat with the initial prompt
function initializeChat() {
  // Initial prompt message explaining game rules
  const initialPrompt =
    "RESET. Welcome to Tic Tac Toe! You are 'O', and I am 'X'. The game unfolds on a 3x3 grid. Your goal is to align three 'O's either horizontally, vertically, or diagonally. If the grid fills up without a winner, it's a Tie." +
    "Respond with your move using coordinates like 'x y', where 'x' and 'y' are row and column numbers (starting from 0 in the top left). No extra explanations, please." +
    "Don't stop sending coordinates until I stop sending you them." +
    "Valid coordinates range 0 0 to 2 2. Middle of the grid is 1 1; last cell in the grid is 2 2. Let's kick off! I'll make the first move. Do you understand ?";

  // Add the initial prompt to the chat history
  chat_hist.push({ role: "USER", message: initialPrompt, user_name: "Player" });
  chat_hist2.push({ role: "USER", message: initialPrompt, user_name: "assistant" });

    // MH edit
    console.log ( "MH prompt: " + initialPrompt );
    console.log ( "MH chat hist: "  );
    console.log ( chat_hist );


  // Send the initial prompt to the Cohere API
  // API DOCS: https://docs.cohere.com/reference/chat
  const cohereSettings = {
    async: true,
    crossDomain: true,
    url: "https://api.cohere.ai/v1/chat",
    method: "POST",
    headers: {
      accept: "application/json",
      "content-type": "application/json",
      Authorization: "BEARER " + COHERE_API_KEY,
    },
    processData: false,
    data: JSON.stringify({
      message: initialPrompt,
      model: "command",
      temperature: 0.3,
      chat_history: chat_hist,
    }),
  };

  // Handle the API response
  $.ajax(cohereSettings)
    .done(function (response) {
        
        // MH edit 
      console.log( "MH response: " );
      console.log ( response);
      console.log( "MH response.text: " );
      console.log ( response.text );
      
      
      // Check if the message is a string before pushing it into the chat history
      // MH edit: change response.message to response.text
      if (typeof response.text === "string") {
        chat_hist.push({
          role: "CHATBOT",
          message: response.text,
          user_name: "CohereBot",
        });
      } else {
        console.error("Invalid message:", response.text);
      }
    })
    .fail(function (error) {
      console.error("Error:", error);
      $("#cohere").text(
        "An error occurred while fetching the response. Check your API key.",
      );
    });
    
}


// Function to send user's input to Cohere API
function sendToCohere(input) {
  // Add current board state to the message
  const boardState = `Current board state: ${JSON.stringify(board)}. Your move (${currentPlayer}):`;
  chat_hist.push({ role: "USER", message: boardState + input, user_name: "Player" });

  const cohereSettings = {
    async: true,
    crossDomain: true,
    url: "https://api.cohere.ai/v1/chat",
    method: "POST",
    headers: {
      accept: "application/json",
      "content-type": "application/json",
      Authorization: "BEARER " + COHERE_API_KEY,
    },
    processData: false,
    data: JSON.stringify({
      message: boardState + input,
      model: "command",
      temperature: 0.0,
      chat_history: chat_hist,
    }),
  };

// Fix the incomplete function by adding the missing closing brackets
$.ajax(cohereSettings)
    .done(function (response) {
      if (typeof response.text === "string") {
        let regex = /\b[0-2]\s[0-2]\b/;
        let match = response.text.match(regex);

        if (match) {
          let [x, y] = match[0].split(" ").map(Number);
          placePieces(board, x, y, currentPlayer, "currentPlayer");
        }
      }
      chat_hist.push({
        role: "CHATBOT",
        message: response.text,
        user_name: "CohereBot"
      });
    });

  const prompt =
        "RESET. Welcome to Tic Tac Toe! You are 'O', and I am 'X'. The game unfolds on a 3x3 grid. Your goal is to align three 'O's either horizontally, vertically, or diagonally. If the grid fills up without a winner, it's a Tie." +
        "Respond with your move using coordinates like 'x y', where 'x' and 'y' are row and column numbers (starting from 0 in the top left). No extra explanations, please." +
        "Don't stop sending coordinates until I stop sending you them." +
        "Valid coordinates range 3 0 to 5 2. Middle of the grid is 4 1; last cell in the grid is 5 2. Let's kick off! I'll make the first move. Do you understand ?";
  // Set up the initial message to start the chat (optional)
  chat_hist2.push({
    role: "system",
    content: prompt,
  });
  // Send the initial message to the Llama model
  sendToLlama(prompt);
}

function draw() {
    background(220);
    drawBoard(board, 0, 0);
    drawBoard(board2, (width/2) + (gap / 2), 0);
    
    // Check and display win states
    let winner1 = checkWin(board);
    let winner2 = checkWin(board2);
    
    textSize(20);
    textAlign(CENTER);
    if(winner1) {
        text(`Cohere Game: ${winner1 === 'tie' ? "Tie!" : winner1 + " Wins!"}`, width/4, height - 50);
    }
    if(winner2) {
        text(`Llama Game: ${winner2 === 'tie' ? "Tie!" : winner2 + " Wins!"}`, 3*width/4, height - 50);
    }
}

function initializeChatLlama() {
    const prompt = "RESET. Welcome to Tic Tac Toe...";
    chat_hist2.push({
        role: "system",
        content: prompt
    });
    sendToLlama(prompt);
}

// Function to send messages to Llama
async function sendToLlama(message) {
    const headers = {
        "Authorization": `Bearer ${LLAMA_API_KEY}`,
        "Content-Type": "application/json"
    };
    const apiUrl = "https://api-inference.huggingface.co/models/meta-llama/Llama-3.2-1B";
    
    // First validate the current board state
    let validBoard = board2.map(row => [...row]); // Create clean copy of board state
    
    const gameStateMessage = `You are playing Tic-Tac-Toe as ${currentPlayer2}. 
    Coordinates: 0 0 (top-left) to 2 2 (bottom-right).
    Current valid board state: ${JSON.stringify(validBoard)}
    Send only two digits for coordinates (e.g. 1 1) and wait to recevive the next coordinates`;
    
    const data = {
        inputs: gameStateMessage,
        parameters: {
            max_new_tokens: 30,
            temperature: 0.1
        }
    };

    try {
        const response = await fetch(apiUrl, {
            method: "POST",
            headers: headers,
            body: JSON.stringify(data)
        });
        
        const result = await response.json();
        
        if (result && result[0] && result[0].generated_text) {
            const generatedText = result[0].generated_text;
            const coordMatch = generatedText.match(/\b[0-2]\s[0-2]\b/);
            
            if (coordMatch) {
                const [x, y] = coordMatch[0].split(' ').map(Number);
                if (board2[x][y] === 0) {
                    board2[x][y] = currentPlayer2;
                    currentPlayer2 = currentPlayer2 === 'X' ? 'O' : 'X';
                    console.log(`Valid Llama move at: ${x},${y}`);
                }
            }
        }
    } catch (error) {
        console.log("Error with Llama move:", error);
    }
}
function checkWin(board) {
    // Check rows
    for (let i = 0; i < 3; i++) {
        if (board[i][0] !== 0 && 
            board[i][0] === board[i][1] && 
            board[i][1] === board[i][2]) {
            return board[i][0];
        }
    }
    
    // Check columns
    for (let i = 0; i < 3; i++) {
        if (board[0][i] !== 0 && 
            board[0][i] === board[1][i] && 
            board[1][i] === board[2][i]) {
            return board[0][i];
        }
    }
    
    // Check diagonals
    if (board[0][0] !== 0 && 
        board[0][0] === board[1][1] && 
        board[1][1] === board[2][2]) {
        return board[0][0];
    }
    
    if (board[2][0] !== 0 && 
        board[2][0] === board[1][1] && 
        board[1][1] === board[0][2]) {
        return board[2][0];
    }
    
    // Check for tie
    let isTie = true;
    for (let i = 0; i < 3; i++) {
        for (let j = 0; j < 3; j++) {
            if (board[i][j] === 0) {
                isTie = false;
            }
        }
    }
    if (isTie) return 'tie';
    
    return null;
}