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;
}