// Cloned by Madalina Triboi on 1 Dec 2023 from World "cohere chatbot api test" by Madalina Triboi// Please leave this clone trail here.// Code guidance from Chat with GPT Model by Dr. Mark Humphrys// It follows the same kind of structure as to understand how to call the API.// AI API that is being used is Cohere.// Similar to OpenAI's APIs but it offers free API keys; thus why I picked it.// Tutorial followed for Tic Tac Toe grid setup in p5.js// https://www.youtube.com/watch?v=8x_omgn3IRg&ab_channel=PattVira// Cohere API key for authenticationvar COHERE_API_KEY ="E6vTBQ2D4AWDQHrv4kA0sIXekaq3BX731TMSjila";// Variable to track whether the game has ended
let gameEnded =false;// Array to store chat historyvar chat_hist =[];// Variable to keep track of the current player ("X" or "O")
let currentPlayer ="X";// Set body style using jQuery
$("body").css({
margin:"25px",
padding:"12px","font-family":"'Poppins', sans-serif","font-family":"'Roboto', sans-serif","font-size":"125%",
color:"#4A4B44",});// Call the initialization function when the page is first loaded
$(document).ready(function(){// MH edit
AB.removeRunHeader();
initializeChat();// Initially hide the board and other elements// Did this in order to send the initialChat to the API to explain game rules;// And to avoid the user clicking on the grid, confusing the API.
$("#p5-container").hide();
$("#end-game").hide();
$("#cohere").hide();});// Function to initialize the chat with the initial promptfunction initializeChat(){// Initial prompt message explaining game rulesconst 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"});// 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/chatconst settings ={
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(settings).done(function(response){// MH edit
console.log("MH response: ");
console.log ( response);
console.log("MH response.text: ");
console.log ( response.text );// Once we have a response, show the board. The API now knows what game we are playing.
showBoard();
$("#start").hide();// Check if the message is a string before pushing it into the chat history// MH edit: change response.message to response.textif(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 show the Tic Tac Toe board and other elements once we received an answer from the APIfunction showBoard(){
$("#p5-container").show();
$("#end-game").show();
$("#cohere").show();}// Dynamically create HTML elements for the Tic Tac Toe game
document.write(`<!DOCTYPE HTML><style>@import url('https://fonts.googleapis.com/css2?family=Poppins&family=Roboto&display=swap');</style><div style='position:absolute; left: 25%; right:25%'><br></br><h2>TicTacToewithCohere AI API </h2><hr style="border-top: 1px dotted #76877D"></hr><br></br><h3 id="start">Fetching API...LoadingGame...</h3><div id="p5-container"></div><div id="end-game"></div><div id=cohere><h3>CohereSays:</h3><p id="text"></p></div></div>`);// Function to send user's input to Cohere APIfunction sendToCohere(input){// If the game has ended, do not make an API callif(gameEnded){
console.log("Game Ended.");return;}// Put input into the chat history so the API has somewhat a clue what the next coordinates should be
chat_hist.push({ role:"USER", message: input, user_name:"Player"});// MH edit
console.log ("MH input: "+ input );
console.log ("MH chat hist: ");
console.log ( chat_hist );// API DOCS: https://docs.cohere.com/reference/chatconst settings ={
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: input,
model:"command",
temperature:0.0,
chat_history: chat_hist,}),};// Handle the API response
$.ajax(settings).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 historyif(typeof response.text ==="string"){// Display API response for the user to see if the API is playing right and not confused
$("#text").text(`${response.text}`);// Use a regex to find the coordinates in the response text// Delimited by boundaries, 1 digit number separated by whitespace
let regex =/\b\d{1} \d{1}\b/;
let match = response.text.match(regex);// If a match was found, split the match into x and y coordinatesif(match){
let [x, y]= match[0].split(" ");
chat_hist.push({
role:"CHATBOT",
message: response.text,
user_name:"CohereBot",});// Draw the move on the canvas
drawMove(parseInt(y), parseInt(x),"O");
console.log(`Move coordinates: ${x} ${y}`);}else{
console.error("No coordinates found in response:", response.text);// Try to get an answer again by calling sendToCohere() again
sendToCohere(input);}}else{
console.error("Invalid message:", response.text);}}).fail(function(error){
console.error("Error:", error);
$("#text").text("An error occurred while fetching the response.");});}// Set up the canvas for drawing the Tic Tac Toe gridfunction setup(){
let canvas = createCanvas(500,500);
canvas.parent("p5-container");// Set parent to the div with id "p5-container"// MH edit ABWorld.canvas = canvas;// so AB screenshot can find this non-standard P5 canvas later
let cellSize = width /3;// Draw the gridfor(let i =0; i <3; i++){for(let j =0; j <3; j++){
stroke(0);
noFill();
rect(i * cellSize, j * cellSize, cellSize, cellSize);}}// Stop redrawing after setup
noLoop();}// Initialize the game board with empty cells
let board =[["","",""],["","",""],["","",""],];// Function to draw a move on the canvasfunction drawMove(x, y, player){// Check if the cell is empty before making a moveif(board[x][y]===""){// Update the board with the move
board[x][y]= player;// Draw the move on the canvas
let cellSize = width /3;
let moveX = x * cellSize + cellSize /2;
let moveY = y * cellSize + cellSize /2;
textSize(32);
textAlign(CENTER, CENTER);if(player ==="X"){
text("X", moveX, moveY);
winner(board);}elseif(player ==="O"){
text("O", moveX, moveY);
winner(board);}}else{
console.error("Cell is already occupied!");
console.log(JSON.stringify(board));// Provide a message indicating that the selected cell is already occupiedconst message =`Cell at ${x} ${y} is already occupied.Analyzethis grid to see where you may be able to find an empty cell ${JSON.stringify(
board,)}.Please choose a different placement.`;
sendToCohere(message);}}// Function to handle mouse click events (user's move)function mousePressed(){// Make a move when the mouse is pressed
let cellSize = width /3;
let i = floor(mouseX / cellSize);
let j = floor(mouseY / cellSize);// Check if the cell is empty before making a moveif(board[i][j]===""){
drawMove(i, j,"X");// Send the user's move to the Cohere API
console.log(`Mouse pressed at ${j} ${i}`);
let move =`${j} ${i}`;
sendToCohere(move);}}// Evaluate the winner of the Tic Tac Toe game// Reference: https://stackoverflow.com/questions/69505095/how-to-detect-tic-tac-toe-winner-in-javascript-with-3-child-arrayfunction winner(board){
winners =newSet();// Columns checkfor(let i =0; i <3; i++){if(
board[0][i]!==""&&newSet([board[0][i], board[1][i], board[2][i]]).size ===1){
winners.add(board[0][i]);}}// Rows checkfor(let i =0; i <3; i++){if(board[i][0]!==""&&newSet(board[i]).size ===1){
winners.add(board[i][0]);}}// Diagonals checkif(
board[1][1]!==""&&(newSet([board[0][0], board[1][1], board[2][2]]).size ===1||newSet([board[0][2], board[1][1], board[2][0]]).size ===1)){
winners.add(board[1][1]);}if(winners.size ===2){return"error";}if(winners.size ===0){// TIEif(board.every((y)=> y.every((z)=> z))){
gameEnded =true;
$("#end-game").html(`<h2>TIE <h2><p>ReloadPageif you want to play again </p>`);}return"incomplete";}if(
winners.values().next().value ==="X"||
winners.values().next().value ==="O"){// WIN
gameEnded =true;
$("#end-game").html(`<h2>WINNER: ${winners.values().next().value}<h2><p>ReloadPageif you want to play again </p>`);}}