Skip to content

Commit

Permalink
Add an AI agent + image
Browse files Browse the repository at this point in the history
  • Loading branch information
Quantumplation committed Nov 14, 2024
1 parent 9cfab0a commit 54325a3
Show file tree
Hide file tree
Showing 7 changed files with 322 additions and 0 deletions.
1 change: 1 addition & 0 deletions ai/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
22 changes: 22 additions & 0 deletions ai/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM node:20-alpine AS base

RUN apk add

WORKDIR /usr/src/app
RUN --mount=type=bind,source=package.json,target=package.json \
--mount=type=bind,source=yarn.lock,target=yarn.lock \
yarn install --frozen-lockfile
USER node

WORKDIR /usr/src
COPY ./ai ./app
COPY ./ai/tsconfig.docker.json ./app/tsconfig.json
COPY ./src/utils/hydra-multiplayer.ts ./app/utils/hydra-multiplayer.ts
COPY ./src/utils/hydra.ts ./app/utils/hydra.ts
COPY ./websockets-doom.js ./websockets-doom.js
COPY ./public/ ./public/


WORKDIR /usr/src/app
EXPOSE 3000
CMD npx -y tsx ai.ts
100 changes: 100 additions & 0 deletions ai/ai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Run as a node process to run a dedicated doom server

import { readFile } from "node:fs/promises";
import { HydraMultiplayer } from "utils/hydra-multiplayer";
import { Lucid, toHex, fromHex } from "lucid-cardano";
import * as bech32 from "bech32-buffer";
import * as ed25519 from "@noble/ed25519";
import { blake2b } from "@noble/hashes/blake2b";

// TODO: should we generate this key, like the UI does? no reason we need to keep it around
let done = false;
const lucid = await Lucid.new(undefined, "Preprod");
const adminKeyFile = process.env.BOT_KEY_FILE ?? "bot.sk";
const adminKey = JSON.parse((await readFile(adminKeyFile)).toString());
const privateKeyBytes = adminKey.cborHex.slice(4);
const sessionKeyBech32 = bech32.encode("ed25519_sk", fromHex(privateKeyBytes));

const publicKeyBytes = await ed25519.getPublicKeyAsync(privateKeyBytes);
const publicKeyHashBytes = blake2b(publicKeyBytes, { dkLen: 224 / 8 });
const publicKeyHashHex = toHex(publicKeyHashBytes);
const keys = {
sessionKeyBech32,
privateKeyBytes,
privateKeyHex: toHex(privateKeyBytes),
publicKeyBytes,
publicKeyHex: toHex(publicKeyBytes),
publicKeyHashBytes,
publicKeyHashHex,
address: lucid.utils.credentialToAddress({
type: "Key",
hash: publicKeyHashHex,
}),
};
console.log("Address: ", keys.address);

const { default: createModule } = await import("../websockets-doom.js");
const module = await createModule({
locateFile: (path, scripts) => {
console.log(scripts + "public/" + path);
return scripts + "public/" + path;
},
noInitialRun: true,
preRun: function (mod: any) {
const files = ["freedoom2.wad", "default.cfg", "Cardano.wad"];
files.forEach((file) => {
mod.FS!.createPreloadedFile("/", file, "../public/" + file, true, true);
});
},
canvas: null as any,
print: (text: string) => {
console.log("stdout:", text);
},
printErr: (text: string) => {
console.error("stderr:", text);
},
onExit: () => {
console.log("Game exited");
done = true;
},
});
global.Module = module;
global.HydraMultiplayer = new HydraMultiplayer(
keys,
"http://localhost:4001",
module,
);

// TODO: modify new-game transaction to record # of players
// TODO: watch for new-game transaction to decide if we're participating in this game

// TODO: generate a fun pet name
const args = [
"-connect",
"1",
"-deathmatch",
"-ai",
"-iwad",
"freedoom2.wad",
"-file",
"Cardano.wad",
"-nodraw",
"-nomouse",
"-nograbmouse",
"-nogui",
"-nomusic",
"-nosound",
"-config",
"default.cfg",
];
try {
module.callMain(args);
} catch (e) {
console.error(e);
}

while (!done) {
await new Promise((resolve) => setTimeout(resolve, 1000));
}

process.exit(0);
12 changes: 12 additions & 0 deletions ai/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "ai-doom",
"type": "module",
"module": "ES2022",
"target": "ES2022",
"dependencies": {
"@noble/ed25519": "^2.1.0",
"@noble/hashes": "^1.5.0",
"bech32-buffer": "^0.2.1",
"lucid-cardano": "^0.10.7"
}
}
11 changes: 11 additions & 0 deletions ai/tsconfig.docker.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"module": "ES2022",
"target": "ES2022",
"paths": {
"utils/*": ["./utils/*"]
}
},
"files": ["ai.ts"],
"references": []
}
11 changes: 11 additions & 0 deletions ai/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"module": "ES2022",
"target": "ES2022",
"paths": {
"utils/*": ["../src/utils/*"]
}
},
"files": ["ai.ts"],
"references": []
}
165 changes: 165 additions & 0 deletions ai/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@noble/ed25519@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-2.1.0.tgz#4bf661de9ee0ad775d41fcacbfc9aeec491f459c"
integrity sha512-KM4qTyXPinyCgMzeYJH/UudpdL+paJXtY3CHtHYZQtBkS8MZoPr4rOikZllIutJe0d06QDQKisyn02gxZ8TcQA==

"@noble/hashes@^1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0"
integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==

"@opentelemetry/api@^1.4.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe"
integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==

"@peculiar/asn1-schema@^2.3.13", "@peculiar/asn1-schema@^2.3.8":
version "2.3.13"
resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.3.13.tgz#ec8509cdcbc0da3abe73fd7e690556b57a61b8f4"
integrity sha512-3Xq3a01WkHRZL8X04Zsfg//mGaA21xlL4tlVn4v2xGT0JStiztATRkMwa5b+f/HXmY2smsiLXYK46Gwgzvfg3g==
dependencies:
asn1js "^3.0.5"
pvtsutils "^1.3.5"
tslib "^2.6.2"

"@peculiar/json-schema@^1.1.12":
version "1.1.12"
resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339"
integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==
dependencies:
tslib "^2.0.0"

"@peculiar/webcrypto@^1.4.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz#9e57174c02c1291051c553600347e12b81469e10"
integrity sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==
dependencies:
"@peculiar/asn1-schema" "^2.3.8"
"@peculiar/json-schema" "^1.1.12"
pvtsutils "^1.3.5"
tslib "^2.6.2"
webcrypto-core "^1.8.0"

asn1js@^3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.5.tgz#5ea36820443dbefb51cc7f88a2ebb5b462114f38"
integrity sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==
dependencies:
pvtsutils "^1.3.2"
pvutils "^1.1.3"
tslib "^2.4.0"

bech32-buffer@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/bech32-buffer/-/bech32-buffer-0.2.1.tgz#8106f2f51bcb2ba1d9fb7718905c3042c5be2fcd"
integrity sha512-fCG1TyZuCN48Sdw97p/IR39fvqpFlWDVpG7qnuU1Uc3+Xtc/0uqAp8U7bMW/bGuVF5CcNVIXwxQsWwUr6un6FQ==

[email protected]:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.2.tgz#49f896d6e858a4a499df85c38fb399b9aff840f8"
integrity sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==

data-uri-to-buffer@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e"
integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==

fetch-blob@^3.1.2, fetch-blob@^3.1.4:
version "3.2.0"
resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
dependencies:
node-domexception "^1.0.0"
web-streams-polyfill "^3.0.3"

formdata-polyfill@^4.0.10:
version "4.0.10"
resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
dependencies:
fetch-blob "^3.1.2"

lucid-cardano@^0.10.7:
version "0.10.10"
resolved "https://registry.yarnpkg.com/lucid-cardano/-/lucid-cardano-0.10.10.tgz#0ef56d6366419b0f740187791655251f54217e05"
integrity sha512-Yp1o8/kbVUgkRpQqllGQCT9I9w70a+uQKSoJdZEHVrEo5MFbT3Vds314Q8ClqgExzN7pj9NHGbiwiow2ik7mUA==
dependencies:
"@peculiar/webcrypto" "^1.4.0"
node-fetch "^3.2.3"
ws "^8.10.0"

node-domexception@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==

node-fetch@^3.2.3:
version "3.3.2"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b"
integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==
dependencies:
data-uri-to-buffer "^4.0.0"
fetch-blob "^3.1.4"
formdata-polyfill "^4.0.10"

prom-client@^15.1.3:
version "15.1.3"
resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-15.1.3.tgz#69fa8de93a88bc9783173db5f758dc1c69fa8fc2"
integrity sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g==
dependencies:
"@opentelemetry/api" "^1.4.0"
tdigest "^0.1.1"

pvtsutils@^1.3.2, pvtsutils@^1.3.5:
version "1.3.5"
resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.5.tgz#b8705b437b7b134cd7fd858f025a23456f1ce910"
integrity sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==
dependencies:
tslib "^2.6.1"

pvutils@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3"
integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==

readline@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c"
integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==

tdigest@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/tdigest/-/tdigest-0.1.2.tgz#96c64bac4ff10746b910b0e23b515794e12faced"
integrity sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==
dependencies:
bintrees "1.0.2"

tslib@^2.0.0, tslib@^2.4.0, tslib@^2.6.1, tslib@^2.6.2, tslib@^2.7.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b"
integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==

web-streams-polyfill@^3.0.3:
version "3.3.3"
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b"
integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==

webcrypto-core@^1.8.0:
version "1.8.1"
resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.8.1.tgz#09d5bd8a9c48e9fbcaf412e06b1ff1a57514ce86"
integrity sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A==
dependencies:
"@peculiar/asn1-schema" "^2.3.13"
"@peculiar/json-schema" "^1.1.12"
asn1js "^3.0.5"
pvtsutils "^1.3.5"
tslib "^2.7.0"

ws@^8.10.0:
version "8.18.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==

0 comments on commit 54325a3

Please sign in to comment.