Skip to content

Commit

Permalink
Added Chess AI
Browse files Browse the repository at this point in the history
  • Loading branch information
cjmalloy committed Sep 2, 2024
1 parent 0cb2ecc commit 201563b
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/app/component/chess/chess.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@for (p of pieces; track p ? p.color + '-' + p.type : i; let i = $index) {
@for (p of pieces; track i; let i = $index) {
<div class="tile {{ color(i) }}"
[class.from]="getCoord(white ? i : 63 - i) === from"
[class.move]="moves.includes(getCoord(white ? i : 63 - i))"
Expand Down
6 changes: 5 additions & 1 deletion src/app/component/chess/chess.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,11 @@ export class ChessComponent implements OnInit, OnChanges, OnDestroy {
this.chess.loadPgn('');
}
} catch (e) {
this.chess.loadPgn(board || '');
try {
this.chess.loadPgn(board || '');
} catch (e) {
console.error(e);
}
}
this.pieces = flatten(this.chess.board());
this.turn = this.chess.turn();
Expand Down
84 changes: 84 additions & 0 deletions src/app/mods/chess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export const chessPlugin: Plugin = {
actions: [
{ event: 'flip', label: $localize`flip` },
],
advancedActions: [
{ tag: 'plugin/delta/chess', labelOff: $localize`play ai`, labelOn: $localize`cancel ai`, title: $localize`Play against an AI opponent.` },
],
// language=CSS
css: `
body.dark-theme {
Expand Down Expand Up @@ -71,6 +74,86 @@ export const chessPlugin: Plugin = {
},
};

export const chessAiPlugin: Plugin = {
tag: 'plugin/delta/chess',
name: $localize`♟️👻️ AI Chess`,
config: {
mod: $localize`♟️ Chess`,
type: 'plugin',
generated: $localize`Generated by jasper-ui ${moment().toISOString()}`,
description: $localize`Play chess against the AI.`,
icons: [{ label: $localize`👻️`, order: -3 }],
timeoutMs: 30_000,
language: 'javascript',
// language=JavaScript
script: `
const axios = require('axios');
const OpenAi = require('openai');
const ref = JSON.parse(require('fs').readFileSync(0, 'utf-8'));
const origin = ref.origin || ''
const config = ref.plugins['plugin/delta/chess'];
const moves = (ref.comment || '').split('\\n').filter(m => !!m.trim());
const color = config?.aiColor.toLowerCase();
if ((color === 'black') !== !!(moves.length % 2)) process.exit(0);
const apiKey = (await axios.get(process.env.JASPER_API + '/api/v1/ref/page', {
headers: {
'Local-Origin': origin || 'default',
'User-Role': 'ROLE_ADMIN',
},
params: { query: (config?.apiKeyTag || '+plugin/secret/openai') + origin },
})).data.content[0].comment;
const prompt =
'You are playing a game of chess against an opponent.\\n' +
'Read the following board in Portable Game Notation (PGN) and reply with the next move.\\n' +
'If the game has ended or is not valid simply reply pass.\\n' +
'Do not include any lists, formatting, additional text. Only reply with either a valid PGN move or the word pass in all lowercase.\\n\\n'
+ ref.comment;
const openai = new OpenAi({ apiKey });
const completion = await openai.chat.completions.create({
model: config?.model || 'gpt-4o',
max_tokens: config?.maxTokens || 4096,
messages: [
{ role: 'system', content: prompt },
{ role: 'user', content: ref.comment || 'New game' },
],
});
const move = completion.choices[0]?.message?.content;
const title = (ref.title.includes(' | ') ? ref.title.substring(0, ref.title.indexOf(' | ')) : ref.title) + ' | ' + move;
delete ref.metadata;
if (move !== 'pass') {
const newBoard = {
...ref,
title,
comment: (ref.comment ? ref.comment + '\\n' : '') + move,
};
console.log(JSON.stringify({
ref: [newBoard],
}));
}
`,
form: [{
key: 'aiColor',
type: 'select',
defaultValue: 'Black',
props: {
label: $localize`AI Color:`,
options: [
{ value: 'Black', label: $localize`Black` },
{ value: 'White', label: $localize`White` },
],
}
}],
},
defaults: {
aiColor: 'Black',
},
schema: {
properties: {
aiColor: { type: 'string' },
},
},
};

export const chessTemplate: Template = {
tag: 'plugin/chess',
name: $localize`♟️ Chess`,
Expand Down Expand Up @@ -135,6 +218,7 @@ export const chessTemplate: Template = {
export const chessMod: Mod = {
plugins: {
chessPlugin,
chessAiPlugin,
},
templates: {
chessTemplate,
Expand Down
29 changes: 25 additions & 4 deletions src/app/mods/delta.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,40 @@
import { $localize } from '@angular/localize/init';
import * as moment from 'moment';
import { Plugin } from '../model/plugin';
import { Mod } from '../model/tag';
import { chessAiPlugin, chessPlugin, chessTemplate } from './chess';

export const deltaPlugin: Plugin = {
tag: 'plugin/delta',
name: $localize`⏳️ Delta`,
config: {
default: true,
mod: $localize`⏳️ Delta`,
generated: $localize`Generated by jasper-ui ${moment().toISOString()}`,
description: $localize`Transform Refs by running scripts.`,
icons: [
{ label: $localize`⏳️`, order: -10 },
{ tag: '+plugin/delta', label: $localize`⏳️`, order: -10, global: true },
{ tag: '_plugin/delta', label: $localize`⏳️`, order: -10, global: true },
{ label: $localize`⏳️`, noResponse: '+plugin/delta', order: -10 },
{ tag: '_plugin/delta', label: $localize`⏳️`, noResponse: '+plugin/delta', order: -10 },
],
filters: [{ query: 'plugin/delta|_plugin/delta|+plugin/delta', label: $localize`⏳️ Working`, group: $localize`Plugins 🧰️` }],
filters: [{ query: 'plugin/delta|_plugin/delta', label: $localize`⏳️ Working`, group: $localize`Plugins 🧰️` }],
},
};

export const deltaSignaturePlugin: Plugin = {
tag: '+plugin/delta',
name: $localize`⏳️ Delta Signature`,
config: {
default: true,
mod: $localize`⏳️ Delta`,
generated: $localize`Generated by jasper-ui ${moment().toISOString()}`,
description: $localize`Transform Refs by running scripts.`,
},
generateMetadata: true,
};

export const deltaMod: Mod = {
plugins: {
deltaPlugin,
deltaSignaturePlugin,
},
};
4 changes: 2 additions & 2 deletions src/app/service/admin.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { cronPlugin } from '../mods/cron';
import { dalleMod } from '../mods/dalle';
import { debugMod } from '../mods/debug';
import { deletePlugin } from '../mods/delete';
import { deltaPlugin } from '../mods/delta';
import { deltaMod, deltaPlugin } from '../mods/delta';
import { htmlPlugin, latexPlugin } from '../mods/editor';
import { emailPlugin } from '../mods/email';
import { embedPlugin } from '../mods/embed';
Expand Down Expand Up @@ -105,7 +105,7 @@ export class AdminService {
...errorMod.plugins,
...remoteOriginMod.plugins,
cronPlugin,
deltaPlugin,
...deltaMod.plugins,
feedPlugin,
deletePlugin,
...mailboxMod.plugins,
Expand Down

0 comments on commit 201563b

Please sign in to comment.