Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Multiplayer setting.
Browse filesHey
@radames
!
I normally uploaded the change to make this space properly multiplayer.
Let's review changes carefully together before merging
- patches/Dockerfile +47 -0
- patches/README.md +36 -0
- patches/patches/App.tsx +141 -0
- patches/patches/Button.tsx +33 -0
- patches/patches/InteractButton.tsx +88 -0
- patches/patches/OAuthLogin.tsx +57 -0
- patches/patches/PixiGame.tsx +132 -0
- patches/patches/PixiStaticMap.tsx +128 -0
- patches/patches/PlayerDetails.tsx +265 -0
- patches/patches/characters.ts +135 -0
- patches/patches/constants.ts +78 -0
- patches/patches/gentle.js +330 -0
- patches/patches/hf.svg +18 -0
- patches/patches/llm.ts +657 -0
- patches/patches/music.ts +135 -0
- patches/patches/run.sh +27 -0
- patches/patches/vite.config.ts +18 -0
- patches/patches/world.ts +273 -0
patches/Dockerfile
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM ubuntu:22.04 as base
|
2 |
+
WORKDIR /app
|
3 |
+
ENV NODE_ENV=production
|
4 |
+
|
5 |
+
FROM base as build
|
6 |
+
|
7 |
+
RUN apt-get update -qq && \
|
8 |
+
apt-get install -y git curl unzip wget gnupg build-essential lsb-release
|
9 |
+
|
10 |
+
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
|
11 |
+
apt-get install -y nodejs
|
12 |
+
|
13 |
+
RUN useradd -m -u 1000 user
|
14 |
+
RUN chown -R user:user /app /usr/local /tmp
|
15 |
+
USER user
|
16 |
+
ENV HOME=/home/user \
|
17 |
+
PATH=/home/user/.local/bin:$PATH
|
18 |
+
|
19 |
+
WORKDIR $HOME/app
|
20 |
+
|
21 |
+
RUN git clone https://github.com/a16z-infra/ai-town.git . && \
|
22 |
+
git checkout f005c46d1759b47bb3ade8d41952a713c4faf331
|
23 |
+
|
24 |
+
RUN npm install --include=dev @huggingface/inference
|
25 |
+
RUN npm install --include=dev @huggingface/hub
|
26 |
+
|
27 |
+
RUN curl -L -O https://github.com/get-convex/convex-backend/releases/download/precompiled-2024-05-07-13337fd/convex-local-backend-x86_64-unknown-linux-gnu.zip && \
|
28 |
+
unzip convex-local-backend-x86_64-unknown-linux-gnu.zip
|
29 |
+
|
30 |
+
COPY ./patches/llm.ts ./convex/util/
|
31 |
+
COPY ./patches/vite.config.ts ./
|
32 |
+
COPY ./patches/constants.ts ./patches/music.ts ./convex/
|
33 |
+
COPY ./patches/characters.ts ./patches/gentle.js ./data/
|
34 |
+
COPY ./patches/PixiGame.tsx ./src/components/PixiGame.tsx
|
35 |
+
COPY ./patches/PixiStaticMap.tsx ./src/components/
|
36 |
+
COPY ./patches/Button.tsx ./src/components/buttons/Button.tsx
|
37 |
+
COPY ./patches/InteractButton.tsx ./src/components/buttons/InteractButton.tsx
|
38 |
+
COPY ./patches/OAuthLogin.tsx ./src/components/buttons/OAuthLogin.tsx
|
39 |
+
COPY ./patches/App.tsx ./src/App.tsx
|
40 |
+
COPY ./patches/world.ts ./convex/world.ts
|
41 |
+
COPY ./patches/PlayerDetails.tsx ./src/components/PlayerDetails.tsx
|
42 |
+
|
43 |
+
COPY ./patches/hf.svg ./assets/hf.svg
|
44 |
+
|
45 |
+
COPY ./patches/run.sh ./
|
46 |
+
|
47 |
+
CMD ["./run.sh"]
|
patches/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: AI Town on HuggingFace
|
3 |
+
emoji: 🏠💻💌🤗
|
4 |
+
colorFrom: green
|
5 |
+
colorTo: red
|
6 |
+
sdk: docker
|
7 |
+
app_port: 5173
|
8 |
+
pinned: false
|
9 |
+
disable_embedding: true
|
10 |
+
# header: mini
|
11 |
+
short_description: AI Town on HuggingFace
|
12 |
+
hf_oauth: true
|
13 |
+
---
|
14 |
+
|
15 |
+
# AI Town 🏠💻💌 on Hugging Face 🤗
|
16 |
+
|
17 |
+
[**Demo on Hugging Face Spaces**](https://huggingface.co/spaces/radames/ai-town)
|
18 |
+
|
19 |
+
AI Town is a very cool project by [Yoko](https://github.com/ykhli) et [al.](https://github.com/a16z-infra/ai-town), a virtual town with live AI characters where they can chat and socialize. You can also interact with them by sending them messages.
|
20 |
+
|
21 |
+
This repository contains a few code patches to make AI Town run on [Hugging Face 🤗 Spaces](https://huggingface.co/spaces), as well as a Dockerfile capable of running [Convex open-source backend](https://github.com/get-convex/convex-backend), the backend and frontend on a single container.
|
22 |
+
|
23 |
+
## How to run locally
|
24 |
+
|
25 |
+
Grab your Hugging Face API token from https://huggingface.co/settings/tokens
|
26 |
+
|
27 |
+
```bash
|
28 |
+
export HF_TOKEN=hf_**********
|
29 |
+
docker build -t ai-town -f Dockerfile .
|
30 |
+
docker run -ti -p 5173:5173 -e LLM_API_KEY=$HF_TOKEN ai-town
|
31 |
+
```
|
32 |
+
|
33 |
+
## How to run on Hugging Face
|
34 |
+
|
35 |
+
You can duplicate this Space https://huggingface.co/spaces/radames/ai-town?duplicate=true, add your `HF_TOKEN`
|
36 |
+
Then you can customize [patches/constants.ts](patches/constants.ts) and [patches/characters.ts](patches/characters.ts) as you wish, as well as the LLM model and embeddings model in [patches/llm.ts](patches/llm.ts).
|
patches/patches/App.tsx
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import Game from './components/Game.tsx';
|
2 |
+
|
3 |
+
import { ToastContainer } from 'react-toastify';
|
4 |
+
import a16zImg from '../assets/a16z.png';
|
5 |
+
import convexImg from '../assets/convex.svg';
|
6 |
+
import starImg from '../assets/star.svg';
|
7 |
+
import helpImg from '../assets/help.svg';
|
8 |
+
// import { UserButton } from '@clerk/clerk-react';
|
9 |
+
// import { Authenticated, Unauthenticated } from 'convex/react';
|
10 |
+
// import LoginButton from './components/buttons/LoginButton.tsx';
|
11 |
+
import { useState } from 'react';
|
12 |
+
import ReactModal from 'react-modal';
|
13 |
+
import MusicButton from './components/buttons/MusicButton.tsx';
|
14 |
+
import Button from './components/buttons/Button.tsx';
|
15 |
+
import InteractButton from './components/buttons/InteractButton.tsx';
|
16 |
+
import FreezeButton from './components/FreezeButton.tsx';
|
17 |
+
import { MAX_HUMAN_PLAYERS } from '../convex/constants.ts';
|
18 |
+
import PoweredByConvex from './components/PoweredByConvex.tsx';
|
19 |
+
import OAuthLogin from './components/buttons/OAuthLogin.tsx';
|
20 |
+
|
21 |
+
export default function Home() {
|
22 |
+
const [helpModalOpen, setHelpModalOpen] = useState(false);
|
23 |
+
return (
|
24 |
+
<main className="relative flex min-h-screen flex-col items-center justify-between font-body game-background">
|
25 |
+
<PoweredByConvex />
|
26 |
+
|
27 |
+
<ReactModal
|
28 |
+
isOpen={helpModalOpen}
|
29 |
+
onRequestClose={() => setHelpModalOpen(false)}
|
30 |
+
style={modalStyles}
|
31 |
+
contentLabel="Help modal"
|
32 |
+
ariaHideApp={false}
|
33 |
+
>
|
34 |
+
<div className="font-body">
|
35 |
+
<h1 className="text-center text-6xl font-bold font-display game-title">Help</h1>
|
36 |
+
<p>
|
37 |
+
Welcome to AI town. AI town supports both anonymous <i>spectators</i> and logged in{' '}
|
38 |
+
<i>interactivity</i>.
|
39 |
+
</p>
|
40 |
+
<h2 className="text-4xl mt-4">Spectating</h2>
|
41 |
+
<p>
|
42 |
+
Click and drag to move around the town, and scroll in and out to zoom. You can click on
|
43 |
+
an individual character to view its chat history.
|
44 |
+
</p>
|
45 |
+
<h2 className="text-4xl mt-4">Interactivity</h2>
|
46 |
+
<p>
|
47 |
+
If you log in, you can join the simulation and directly talk to different agents! After
|
48 |
+
logging in, click the "Interact" button, and your character will appear somewhere on the
|
49 |
+
map with a highlighted circle underneath you.
|
50 |
+
</p>
|
51 |
+
<p className="text-2xl mt-2">Controls:</p>
|
52 |
+
<p className="mt-4">Click to navigate around.</p>
|
53 |
+
<p className="mt-4">
|
54 |
+
To talk to an agent, click on them and then click "Start conversation," which will ask
|
55 |
+
them to start walking towards you. Once they're nearby, the conversation will start, and
|
56 |
+
you can speak to each other. You can leave at any time by closing the conversation pane
|
57 |
+
or moving away. They may propose a conversation to you - you'll see a button to accept
|
58 |
+
in the messages panel.
|
59 |
+
</p>
|
60 |
+
<p className="mt-4">
|
61 |
+
AI town only supports {MAX_HUMAN_PLAYERS} humans at a time. If you're idle for five
|
62 |
+
minutes, you'll be automatically removed from the simulation.
|
63 |
+
</p>
|
64 |
+
</div>
|
65 |
+
</ReactModal>
|
66 |
+
{/*<div className="p-3 absolute top-0 right-0 z-10 text-2xl">
|
67 |
+
<Authenticated>
|
68 |
+
<UserButton afterSignOutUrl="/ai-town" />
|
69 |
+
</Authenticated>
|
70 |
+
|
71 |
+
<Unauthenticated>
|
72 |
+
<LoginButton />
|
73 |
+
</Unauthenticated>
|
74 |
+
</div> */}
|
75 |
+
|
76 |
+
<div className="w-full lg:h-screen min-h-screen relative isolate overflow-hidden lg:p-8 shadow-2xl flex flex-col justify-start">
|
77 |
+
<h1 className="mx-auto text-4xl p-3 sm:text-8xl lg:text-9xl font-bold font-display leading-none tracking-wide game-title w-full text-left sm:text-center sm:w-auto">
|
78 |
+
AI Town
|
79 |
+
</h1>
|
80 |
+
|
81 |
+
<div className="max-w-xs md:max-w-xl lg:max-w-none mx-auto my-4 text-center text-base sm:text-xl md:text-2xl text-white leading-tight shadow-solid">
|
82 |
+
A virtual town where AI characters live, chat and socialize.
|
83 |
+
{/* <Unauthenticated>
|
84 |
+
<div className="my-1.5 sm:my-0" />
|
85 |
+
Log in to join the town
|
86 |
+
<br className="block sm:hidden" /> and the conversation!
|
87 |
+
</Unauthenticated> */}
|
88 |
+
</div>
|
89 |
+
|
90 |
+
<Game />
|
91 |
+
|
92 |
+
<footer className="justify-end bottom-0 left-0 w-full flex items-center mt-4 gap-3 p-6 flex-wrap pointer-events-none">
|
93 |
+
<div className="flex gap-4 flex-grow pointer-events-none">
|
94 |
+
{/*
|
95 |
+
Users shall not be able freeze in multiplayer
|
96 |
+
<FreezeButton />
|
97 |
+
*/}
|
98 |
+
<MusicButton />
|
99 |
+
<Button href="https://github.com/a16z-infra/ai-town" imgUrl={starImg}>
|
100 |
+
Star
|
101 |
+
</Button>
|
102 |
+
<InteractButton />
|
103 |
+
<Button imgUrl={helpImg} onClick={() => setHelpModalOpen(true)}>
|
104 |
+
Help
|
105 |
+
</Button>
|
106 |
+
<OAuthLogin />
|
107 |
+
</div>
|
108 |
+
<a href="https://a16z.com" target="_blank">
|
109 |
+
<img className="w-8 h-8 pointer-events-auto" src={a16zImg} alt="a16z" />
|
110 |
+
</a>
|
111 |
+
<a href="https://convex.dev" target="_blank">
|
112 |
+
<img className="w-20 h-8 pointer-events-auto" src={convexImg} alt="Convex" />
|
113 |
+
</a>
|
114 |
+
</footer>
|
115 |
+
<ToastContainer position="bottom-right" autoClose={2000} closeOnClick theme="dark" />
|
116 |
+
</div>
|
117 |
+
</main>
|
118 |
+
);
|
119 |
+
}
|
120 |
+
|
121 |
+
const modalStyles = {
|
122 |
+
overlay: {
|
123 |
+
backgroundColor: 'rgb(0, 0, 0, 75%)',
|
124 |
+
zIndex: 12,
|
125 |
+
},
|
126 |
+
content: {
|
127 |
+
top: '50%',
|
128 |
+
left: '50%',
|
129 |
+
right: 'auto',
|
130 |
+
bottom: 'auto',
|
131 |
+
marginRight: '-50%',
|
132 |
+
transform: 'translate(-50%, -50%)',
|
133 |
+
maxWidth: '50%',
|
134 |
+
|
135 |
+
border: '10px solid rgb(23, 20, 33)',
|
136 |
+
borderRadius: '0',
|
137 |
+
background: 'rgb(35, 38, 58)',
|
138 |
+
color: 'white',
|
139 |
+
fontFamily: '"Upheaval Pro", "sans-serif"',
|
140 |
+
},
|
141 |
+
};
|
patches/patches/Button.tsx
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import clsx from 'clsx';
|
2 |
+
import { MouseEventHandler, ReactNode } from 'react';
|
3 |
+
|
4 |
+
export default function Button(props: {
|
5 |
+
className?: string;
|
6 |
+
href?: string;
|
7 |
+
imgUrl: string;
|
8 |
+
onClick?: MouseEventHandler;
|
9 |
+
title?: string;
|
10 |
+
children: ReactNode;
|
11 |
+
}) {
|
12 |
+
return (
|
13 |
+
<a
|
14 |
+
className={clsx(
|
15 |
+
'button text-white shadow-solid text-xl pointer-events-auto',
|
16 |
+
props.className,
|
17 |
+
)}
|
18 |
+
href={props.href}
|
19 |
+
title={props.title}
|
20 |
+
onClick={props.onClick}
|
21 |
+
target="_blank"
|
22 |
+
>
|
23 |
+
<div className="inline-block bg-clay-700">
|
24 |
+
<span>
|
25 |
+
<div className="inline-flex h-full items-center gap-4">
|
26 |
+
<img className="w-4 h-4 sm:w-[30px] sm:h-[30px]" src={props.imgUrl} />
|
27 |
+
{props.children}
|
28 |
+
</div>
|
29 |
+
</span>
|
30 |
+
</div>
|
31 |
+
</a>
|
32 |
+
);
|
33 |
+
}
|
patches/patches/InteractButton.tsx
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import Button from './Button';
|
2 |
+
import { toast } from 'react-toastify';
|
3 |
+
import interactImg from '../../../assets/interact.svg';
|
4 |
+
import { useConvex, useMutation, useQuery } from 'convex/react';
|
5 |
+
import { api } from '../../../convex/_generated/api';
|
6 |
+
// import { SignInButton } from '@clerk/clerk-react';
|
7 |
+
import { ConvexError } from 'convex/values';
|
8 |
+
import { Id } from '../../../convex/_generated/dataModel';
|
9 |
+
import { useCallback } from 'react';
|
10 |
+
import { waitForInput } from '../../hooks/sendInput';
|
11 |
+
import { useServerGame } from '../../hooks/serverGame';
|
12 |
+
|
13 |
+
export default function InteractButton() {
|
14 |
+
// const { isAuthenticated } = useConvexAuth();
|
15 |
+
const worldStatus = useQuery(api.world.defaultWorldStatus);
|
16 |
+
const worldId = worldStatus?.worldId;
|
17 |
+
const game = useServerGame(worldId);
|
18 |
+
const oauth = JSON.parse(localStorage.getItem('oauth'));
|
19 |
+
const oauthToken = oauth ? oauth.userInfo.fullname : undefined;
|
20 |
+
console.log(oauthToken)
|
21 |
+
const humanTokenIdentifier = useQuery(api.world.userStatus, worldId ? { worldId, oauthToken } : 'skip');
|
22 |
+
const userPlayerId =
|
23 |
+
game && [...game.world.players.values()].find((p) => p.human === humanTokenIdentifier)?.id;
|
24 |
+
const join = useMutation(api.world.joinWorld);
|
25 |
+
const leave = useMutation(api.world.leaveWorld);
|
26 |
+
const isPlaying = !!userPlayerId;
|
27 |
+
|
28 |
+
const convex = useConvex();
|
29 |
+
const joinInput = useCallback(
|
30 |
+
async (worldId: Id<'worlds'>) => {
|
31 |
+
let inputId;
|
32 |
+
try {
|
33 |
+
inputId = await join({ worldId, oauthToken });
|
34 |
+
} catch (e: any) {
|
35 |
+
if (e instanceof ConvexError) {
|
36 |
+
toast.error(e.data);
|
37 |
+
return;
|
38 |
+
}
|
39 |
+
throw e;
|
40 |
+
}
|
41 |
+
try {
|
42 |
+
await waitForInput(convex, inputId);
|
43 |
+
} catch (e: any) {
|
44 |
+
toast.error(e.message);
|
45 |
+
}
|
46 |
+
},
|
47 |
+
[convex, join, oauthToken],
|
48 |
+
);
|
49 |
+
|
50 |
+
|
51 |
+
const joinOrLeaveGame = () => {
|
52 |
+
if (
|
53 |
+
!worldId ||
|
54 |
+
// || !isAuthenticated
|
55 |
+
game === undefined
|
56 |
+
) {
|
57 |
+
return;
|
58 |
+
}
|
59 |
+
if (isPlaying) {
|
60 |
+
console.log(`Leaving game for player ${userPlayerId}`);
|
61 |
+
void leave({ worldId , oauthToken});
|
62 |
+
} else {
|
63 |
+
console.log(`Joining game`);
|
64 |
+
void joinInput(worldId);
|
65 |
+
}
|
66 |
+
};
|
67 |
+
// if (!isAuthenticated || game === undefined) {
|
68 |
+
// return (
|
69 |
+
// <SignInButton>
|
70 |
+
// <button className="button text-white shadow-solid text-2xl pointer-events-auto">
|
71 |
+
// <div className="inline-block bg-clay-700">
|
72 |
+
// <span>
|
73 |
+
// <div className="inline-flex h-full items-center gap-4">
|
74 |
+
// <img className="w-4 h-4 sm:w-[30px] sm:h-[30px]" src={interactImg} />
|
75 |
+
// Interact
|
76 |
+
// </div>
|
77 |
+
// </span>
|
78 |
+
// </div>
|
79 |
+
// </button>
|
80 |
+
// </SignInButton>
|
81 |
+
// );
|
82 |
+
// }
|
83 |
+
return (
|
84 |
+
<Button imgUrl={interactImg} onClick={joinOrLeaveGame}>
|
85 |
+
{isPlaying ? 'Leave' : 'Interact'}
|
86 |
+
</Button>
|
87 |
+
);
|
88 |
+
}
|
patches/patches/OAuthLogin.tsx
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { useState, useEffect } from 'react';
|
2 |
+
import Button from './Button';
|
3 |
+
import hf from '../../../assets/hf.svg';
|
4 |
+
import { oauthLoginUrl, oauthHandleRedirectIfPresent } from '@huggingface/hub';
|
5 |
+
|
6 |
+
const OAuthLogin = () => {
|
7 |
+
const [isSignedIn, setIsSignedIn] = useState(false);
|
8 |
+
|
9 |
+
useEffect(() => {
|
10 |
+
const checkAuthStatus = async () => {
|
11 |
+
let oauthResult = localStorage.getItem('oauth');
|
12 |
+
if (oauthResult) {
|
13 |
+
try {
|
14 |
+
oauthResult = JSON.parse(oauthResult);
|
15 |
+
} catch {
|
16 |
+
oauthResult = null;
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
if (!oauthResult) {
|
21 |
+
oauthResult = await oauthHandleRedirectIfPresent();
|
22 |
+
if (oauthResult) {
|
23 |
+
localStorage.setItem('oauth', JSON.stringify(oauthResult));
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
setIsSignedIn(!!oauthResult);
|
28 |
+
};
|
29 |
+
|
30 |
+
checkAuthStatus();
|
31 |
+
}, []);
|
32 |
+
|
33 |
+
const handleSignIn = async () => {
|
34 |
+
let clientId = import.meta.env.VITE_OAUTH_CLIENT_ID;
|
35 |
+
window.location.href = await oauthLoginUrl({ clientId });
|
36 |
+
};
|
37 |
+
|
38 |
+
const handleSignOut = () => {
|
39 |
+
localStorage.removeItem('oauth');
|
40 |
+
window.location.href = window.location.href.replace(/\?.*$/, '');
|
41 |
+
setIsSignedIn(false);
|
42 |
+
};
|
43 |
+
|
44 |
+
return (
|
45 |
+
<>
|
46 |
+
{isSignedIn ? (
|
47 |
+
<Button id="signout" imgUrl={hf} onClick={handleSignOut}>Sign out</Button>
|
48 |
+
) : (
|
49 |
+
<Button id="signin" imgUrl={hf} onClick={handleSignIn}>
|
50 |
+
Sign in with Hugging Face
|
51 |
+
</Button>
|
52 |
+
)}
|
53 |
+
</>
|
54 |
+
);
|
55 |
+
};
|
56 |
+
|
57 |
+
export default OAuthLogin;
|
patches/patches/PixiGame.tsx
ADDED
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import * as PIXI from 'pixi.js';
|
2 |
+
import { useApp } from '@pixi/react';
|
3 |
+
import { Player, SelectElement } from './Player.tsx';
|
4 |
+
import { useEffect, useRef, useState } from 'react';
|
5 |
+
import { PixiStaticMap } from './PixiStaticMap.tsx';
|
6 |
+
import PixiViewport from './PixiViewport.tsx';
|
7 |
+
import { Viewport } from 'pixi-viewport';
|
8 |
+
import { Id } from '../../convex/_generated/dataModel';
|
9 |
+
import { useQuery } from 'convex/react';
|
10 |
+
import { api } from '../../convex/_generated/api.js';
|
11 |
+
import { useSendInput } from '../hooks/sendInput.ts';
|
12 |
+
import { toastOnError } from '../toasts.ts';
|
13 |
+
import { DebugPath } from './DebugPath.tsx';
|
14 |
+
import { PositionIndicator } from './PositionIndicator.tsx';
|
15 |
+
import { SHOW_DEBUG_UI } from './Game.tsx';
|
16 |
+
import { ServerGame } from '../hooks/serverGame.ts';
|
17 |
+
|
18 |
+
export const PixiGame = (props: {
|
19 |
+
worldId: Id<'worlds'>;
|
20 |
+
engineId: Id<'engines'>;
|
21 |
+
game: ServerGame;
|
22 |
+
historicalTime: number | undefined;
|
23 |
+
width: number;
|
24 |
+
height: number;
|
25 |
+
setSelectedElement: SelectElement;
|
26 |
+
}) => {
|
27 |
+
// PIXI setup.
|
28 |
+
const pixiApp = useApp();
|
29 |
+
const viewportRef = useRef<Viewport | undefined>();
|
30 |
+
const oauth = JSON.parse(localStorage.getItem('oauth'));
|
31 |
+
const oauthToken = oauth ? oauth.userInfo.fullname : undefined;
|
32 |
+
const humanTokenIdentifier = useQuery(api.world.userStatus, { worldId: props.worldId, oauthToken }) ?? null;
|
33 |
+
const humanPlayerId = [...props.game.world.players.values()].find(
|
34 |
+
(p) => p.human === humanTokenIdentifier,
|
35 |
+
)?.id;
|
36 |
+
|
37 |
+
const moveTo = useSendInput(props.engineId, 'moveTo');
|
38 |
+
|
39 |
+
// Interaction for clicking on the world to navigate.
|
40 |
+
const dragStart = useRef<{ screenX: number; screenY: number } | null>(null);
|
41 |
+
const onMapPointerDown = (e: any) => {
|
42 |
+
// https://pixijs.download/dev/docs/PIXI.FederatedPointerEvent.html
|
43 |
+
dragStart.current = { screenX: e.screenX, screenY: e.screenY };
|
44 |
+
};
|
45 |
+
|
46 |
+
const [lastDestination, setLastDestination] = useState<{
|
47 |
+
x: number;
|
48 |
+
y: number;
|
49 |
+
t: number;
|
50 |
+
} | null>(null);
|
51 |
+
const onMapPointerUp = async (e: any) => {
|
52 |
+
if (dragStart.current) {
|
53 |
+
const { screenX, screenY } = dragStart.current;
|
54 |
+
dragStart.current = null;
|
55 |
+
const [dx, dy] = [screenX - e.screenX, screenY - e.screenY];
|
56 |
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
57 |
+
if (dist > 10) {
|
58 |
+
console.log(`Skipping navigation on drag event (${dist}px)`);
|
59 |
+
return;
|
60 |
+
}
|
61 |
+
}
|
62 |
+
if (!humanPlayerId) {
|
63 |
+
return;
|
64 |
+
}
|
65 |
+
const viewport = viewportRef.current;
|
66 |
+
if (!viewport) {
|
67 |
+
return;
|
68 |
+
}
|
69 |
+
const gameSpacePx = viewport.toWorld(e.screenX, e.screenY);
|
70 |
+
const tileDim = props.game.worldMap.tileDim;
|
71 |
+
const gameSpaceTiles = {
|
72 |
+
x: gameSpacePx.x / tileDim,
|
73 |
+
y: gameSpacePx.y / tileDim,
|
74 |
+
};
|
75 |
+
setLastDestination({ t: Date.now(), ...gameSpaceTiles });
|
76 |
+
const roundedTiles = {
|
77 |
+
x: Math.floor(gameSpaceTiles.x),
|
78 |
+
y: Math.floor(gameSpaceTiles.y),
|
79 |
+
};
|
80 |
+
console.log(`Moving to ${JSON.stringify(roundedTiles)}`);
|
81 |
+
await toastOnError(moveTo({ playerId: humanPlayerId, destination: roundedTiles }));
|
82 |
+
};
|
83 |
+
const { width, height, tileDim } = props.game.worldMap;
|
84 |
+
const players = [...props.game.world.players.values()];
|
85 |
+
|
86 |
+
// Zoom on the user’s avatar when it is created
|
87 |
+
useEffect(() => {
|
88 |
+
if (!viewportRef.current || humanPlayerId === undefined) return;
|
89 |
+
|
90 |
+
const humanPlayer = props.game.world.players.get(humanPlayerId)!;
|
91 |
+
viewportRef.current.animate({
|
92 |
+
position: new PIXI.Point(humanPlayer.position.x * tileDim, humanPlayer.position.y * tileDim),
|
93 |
+
scale: 1.5,
|
94 |
+
});
|
95 |
+
}, [humanPlayerId]);
|
96 |
+
|
97 |
+
return (
|
98 |
+
<PixiViewport
|
99 |
+
app={pixiApp}
|
100 |
+
screenWidth={props.width}
|
101 |
+
screenHeight={props.height}
|
102 |
+
worldWidth={width * tileDim}
|
103 |
+
worldHeight={height * tileDim}
|
104 |
+
viewportRef={viewportRef}
|
105 |
+
>
|
106 |
+
<PixiStaticMap
|
107 |
+
map={props.game.worldMap}
|
108 |
+
onpointerup={onMapPointerUp}
|
109 |
+
onpointerdown={onMapPointerDown}
|
110 |
+
/>
|
111 |
+
{players.map(
|
112 |
+
(p) =>
|
113 |
+
// Only show the path for the human player in non-debug mode.
|
114 |
+
(SHOW_DEBUG_UI || p.id === humanPlayerId) && (
|
115 |
+
<DebugPath key={`path-${p.id}`} player={p} tileDim={tileDim} />
|
116 |
+
),
|
117 |
+
)}
|
118 |
+
{lastDestination && <PositionIndicator destination={lastDestination} tileDim={tileDim} />}
|
119 |
+
{players.map((p) => (
|
120 |
+
<Player
|
121 |
+
key={`player-${p.id}`}
|
122 |
+
game={props.game}
|
123 |
+
player={p}
|
124 |
+
isViewer={p.id === humanPlayerId}
|
125 |
+
onClick={props.setSelectedElement}
|
126 |
+
historicalTime={props.historicalTime}
|
127 |
+
/>
|
128 |
+
))}
|
129 |
+
</PixiViewport>
|
130 |
+
);
|
131 |
+
};
|
132 |
+
export default PixiGame;
|
patches/patches/PixiStaticMap.tsx
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { PixiComponent, applyDefaultProps } from '@pixi/react';
|
2 |
+
import * as PIXI from 'pixi.js';
|
3 |
+
import { AnimatedSprite, WorldMap } from '../../convex/aiTown/worldMap';
|
4 |
+
import * as campfire from '../../data/animations/campfire.json';
|
5 |
+
import * as gentlesparkle from '../../data/animations/gentlesparkle.json';
|
6 |
+
import * as gentlewaterfall from '../../data/animations/gentlewaterfall.json';
|
7 |
+
import * as gentlesplash from '../../data/animations/gentlesplash.json';
|
8 |
+
import * as windmill from '../../data/animations/windmill.json';
|
9 |
+
|
10 |
+
const animations = {
|
11 |
+
'campfire.json': { spritesheet: campfire, url: '/assets/spritesheets/campfire.png' },
|
12 |
+
'gentlesparkle.json': {
|
13 |
+
spritesheet: gentlesparkle,
|
14 |
+
url: '/assets/spritesheets/gentlesparkle32.png',
|
15 |
+
},
|
16 |
+
'gentlewaterfall.json': {
|
17 |
+
spritesheet: gentlewaterfall,
|
18 |
+
url: '/assets/spritesheets/gentlewaterfall32.png',
|
19 |
+
},
|
20 |
+
'windmill.json': { spritesheet: windmill, url: '/assets/spritesheets/windmill.png' },
|
21 |
+
'gentlesplash.json': {
|
22 |
+
spritesheet: gentlesplash,
|
23 |
+
url: '/assets/spritesheets/gentlewaterfall32.png',
|
24 |
+
},
|
25 |
+
};
|
26 |
+
|
27 |
+
export const PixiStaticMap = PixiComponent('StaticMap', {
|
28 |
+
create: (props: { map: WorldMap; [k: string]: any }) => {
|
29 |
+
const map = props.map;
|
30 |
+
const numxtiles = Math.floor(map.tileSetDimX / map.tileDim);
|
31 |
+
const numytiles = Math.floor(map.tileSetDimY / map.tileDim);
|
32 |
+
const bt = PIXI.BaseTexture.from(map.tileSetUrl, {
|
33 |
+
scaleMode: PIXI.SCALE_MODES.NEAREST,
|
34 |
+
});
|
35 |
+
|
36 |
+
const tiles = [];
|
37 |
+
for (let x = 0; x < numxtiles; x++) {
|
38 |
+
for (let y = 0; y < numytiles; y++) {
|
39 |
+
tiles[x + y * numxtiles] = new PIXI.Texture(
|
40 |
+
bt,
|
41 |
+
new PIXI.Rectangle(x * map.tileDim, y * map.tileDim, map.tileDim, map.tileDim),
|
42 |
+
);
|
43 |
+
}
|
44 |
+
}
|
45 |
+
const screenxtiles = map.bgTiles[0].length;
|
46 |
+
const screenytiles = map.bgTiles[0][0].length;
|
47 |
+
|
48 |
+
const container = new PIXI.Container();
|
49 |
+
const allLayers = [...map.bgTiles, ...map.objectTiles];
|
50 |
+
|
51 |
+
// blit bg & object layers of map onto canvas
|
52 |
+
for (let i = 0; i < screenxtiles * screenytiles; i++) {
|
53 |
+
const x = i % screenxtiles;
|
54 |
+
const y = Math.floor(i / screenxtiles);
|
55 |
+
const xPx = x * map.tileDim;
|
56 |
+
const yPx = y * map.tileDim;
|
57 |
+
|
58 |
+
// Add all layers of backgrounds.
|
59 |
+
for (const layer of allLayers) {
|
60 |
+
const tileIndex = layer[x][y];
|
61 |
+
// Some layers may not have tiles at this location.
|
62 |
+
if (tileIndex === -1) continue;
|
63 |
+
const ctile = new PIXI.Sprite(tiles[tileIndex]);
|
64 |
+
ctile.x = xPx;
|
65 |
+
ctile.y = yPx;
|
66 |
+
container.addChild(ctile);
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
// TODO: Add layers.
|
71 |
+
const spritesBySheet = new Map<string, AnimatedSprite[]>();
|
72 |
+
for (const sprite of map.animatedSprites) {
|
73 |
+
const sheet = sprite.sheet;
|
74 |
+
if (!spritesBySheet.has(sheet)) {
|
75 |
+
spritesBySheet.set(sheet, []);
|
76 |
+
}
|
77 |
+
spritesBySheet.get(sheet)!.push(sprite);
|
78 |
+
}
|
79 |
+
for (const [sheet, sprites] of spritesBySheet.entries()) {
|
80 |
+
const animation = (animations as any)[sheet];
|
81 |
+
if (!animation) {
|
82 |
+
console.error('Could not find animation', sheet);
|
83 |
+
continue;
|
84 |
+
}
|
85 |
+
const { spritesheet, url } = animation;
|
86 |
+
const texture = PIXI.BaseTexture.from(url, {
|
87 |
+
scaleMode: PIXI.SCALE_MODES.NEAREST,
|
88 |
+
});
|
89 |
+
const spriteSheet = new PIXI.Spritesheet(texture, spritesheet);
|
90 |
+
spriteSheet.parse().then(() => {
|
91 |
+
for (const sprite of sprites) {
|
92 |
+
const pixiAnimation = spriteSheet.animations[sprite.animation];
|
93 |
+
if (!pixiAnimation) {
|
94 |
+
console.error('Failed to load animation', sprite);
|
95 |
+
continue;
|
96 |
+
}
|
97 |
+
const pixiSprite = new PIXI.AnimatedSprite(pixiAnimation);
|
98 |
+
pixiSprite.animationSpeed = 0.1;
|
99 |
+
pixiSprite.autoUpdate = true;
|
100 |
+
pixiSprite.x = sprite.x;
|
101 |
+
pixiSprite.y = sprite.y;
|
102 |
+
pixiSprite.width = sprite.w;
|
103 |
+
pixiSprite.height = sprite.h;
|
104 |
+
container.addChild(pixiSprite);
|
105 |
+
pixiSprite.play();
|
106 |
+
}
|
107 |
+
});
|
108 |
+
}
|
109 |
+
|
110 |
+
container.x = 0;
|
111 |
+
container.y = 0;
|
112 |
+
|
113 |
+
// Set the hit area manually to ensure `pointerdown` events are delivered to this container.
|
114 |
+
container.interactive = true;
|
115 |
+
container.hitArea = new PIXI.Rectangle(
|
116 |
+
0,
|
117 |
+
0,
|
118 |
+
screenxtiles * map.tileDim,
|
119 |
+
screenytiles * map.tileDim,
|
120 |
+
);
|
121 |
+
|
122 |
+
return container;
|
123 |
+
},
|
124 |
+
|
125 |
+
applyProps: (instance, oldProps, newProps) => {
|
126 |
+
applyDefaultProps(instance, oldProps, newProps);
|
127 |
+
},
|
128 |
+
});
|
patches/patches/PlayerDetails.tsx
ADDED
@@ -0,0 +1,265 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { useQuery } from 'convex/react';
|
2 |
+
import { api } from '../../convex/_generated/api';
|
3 |
+
import { Id } from '../../convex/_generated/dataModel';
|
4 |
+
import closeImg from '../../assets/close.svg';
|
5 |
+
import { SelectElement } from './Player';
|
6 |
+
import { Messages } from './Messages';
|
7 |
+
import { toastOnError } from '../toasts';
|
8 |
+
import { useSendInput } from '../hooks/sendInput';
|
9 |
+
import { Player } from '../../convex/aiTown/player';
|
10 |
+
import { GameId } from '../../convex/aiTown/ids';
|
11 |
+
import { ServerGame } from '../hooks/serverGame';
|
12 |
+
|
13 |
+
export default function PlayerDetails({
|
14 |
+
worldId,
|
15 |
+
engineId,
|
16 |
+
game,
|
17 |
+
playerId,
|
18 |
+
setSelectedElement,
|
19 |
+
scrollViewRef,
|
20 |
+
}: {
|
21 |
+
worldId: Id<'worlds'>;
|
22 |
+
engineId: Id<'engines'>;
|
23 |
+
game: ServerGame;
|
24 |
+
playerId?: GameId<'players'>;
|
25 |
+
setSelectedElement: SelectElement;
|
26 |
+
scrollViewRef: React.RefObject<HTMLDivElement>;
|
27 |
+
}) {
|
28 |
+
const oauth = JSON.parse(localStorage.getItem('oauth'));
|
29 |
+
const oauthToken = oauth ? oauth.userInfo.fullname : undefined;
|
30 |
+
const humanTokenIdentifier = useQuery(api.world.userStatus, { worldId, oauthToken });
|
31 |
+
|
32 |
+
const players = [...game.world.players.values()];
|
33 |
+
const humanPlayer = players.find((p) => p.human === humanTokenIdentifier);
|
34 |
+
const humanConversation = humanPlayer ? game.world.playerConversation(humanPlayer) : undefined;
|
35 |
+
// Always select the other player if we're in a conversation with them.
|
36 |
+
if (humanPlayer && humanConversation) {
|
37 |
+
const otherPlayerIds = [...humanConversation.participants.keys()].filter(
|
38 |
+
(p) => p !== humanPlayer.id,
|
39 |
+
);
|
40 |
+
playerId = otherPlayerIds[0];
|
41 |
+
}
|
42 |
+
|
43 |
+
const player = playerId && game.world.players.get(playerId);
|
44 |
+
const playerConversation = player && game.world.playerConversation(player);
|
45 |
+
|
46 |
+
const previousConversation = useQuery(
|
47 |
+
api.world.previousConversation,
|
48 |
+
playerId ? { worldId, playerId } : 'skip',
|
49 |
+
);
|
50 |
+
|
51 |
+
const playerDescription = playerId && game.playerDescriptions.get(playerId);
|
52 |
+
|
53 |
+
const startConversation = useSendInput(engineId, 'startConversation');
|
54 |
+
const acceptInvite = useSendInput(engineId, 'acceptInvite');
|
55 |
+
const rejectInvite = useSendInput(engineId, 'rejectInvite');
|
56 |
+
const leaveConversation = useSendInput(engineId, 'leaveConversation');
|
57 |
+
|
58 |
+
if (!playerId) {
|
59 |
+
return (
|
60 |
+
<div className="h-full text-xl flex text-center items-center p-4">
|
61 |
+
Click on an agent on the map to see chat history.
|
62 |
+
</div>
|
63 |
+
);
|
64 |
+
}
|
65 |
+
if (!player) {
|
66 |
+
return null;
|
67 |
+
}
|
68 |
+
const isMe = humanPlayer && player.id === humanPlayer.id;
|
69 |
+
const canInvite = !isMe && !playerConversation && humanPlayer && !humanConversation;
|
70 |
+
const sameConversation =
|
71 |
+
!isMe &&
|
72 |
+
humanPlayer &&
|
73 |
+
humanConversation &&
|
74 |
+
playerConversation &&
|
75 |
+
humanConversation.id === playerConversation.id;
|
76 |
+
|
77 |
+
const humanStatus =
|
78 |
+
humanPlayer && humanConversation && humanConversation.participants.get(humanPlayer.id)?.status;
|
79 |
+
const playerStatus = playerConversation && playerConversation.participants.get(playerId)?.status;
|
80 |
+
|
81 |
+
const haveInvite = sameConversation && humanStatus?.kind === 'invited';
|
82 |
+
const waitingForAccept =
|
83 |
+
sameConversation && playerConversation.participants.get(playerId)?.status.kind === 'invited';
|
84 |
+
const waitingForNearby =
|
85 |
+
sameConversation && playerStatus?.kind === 'walkingOver' && humanStatus?.kind === 'walkingOver';
|
86 |
+
|
87 |
+
const inConversationWithMe =
|
88 |
+
sameConversation &&
|
89 |
+
playerStatus?.kind === 'participating' &&
|
90 |
+
humanStatus?.kind === 'participating';
|
91 |
+
|
92 |
+
const onStartConversation = async () => {
|
93 |
+
if (!humanPlayer || !playerId) {
|
94 |
+
return;
|
95 |
+
}
|
96 |
+
console.log(`Starting conversation`);
|
97 |
+
await toastOnError(startConversation({ playerId: humanPlayer.id, invitee: playerId }));
|
98 |
+
};
|
99 |
+
const onAcceptInvite = async () => {
|
100 |
+
if (!humanPlayer || !humanConversation || !playerId) {
|
101 |
+
return;
|
102 |
+
}
|
103 |
+
await toastOnError(
|
104 |
+
acceptInvite({
|
105 |
+
playerId: humanPlayer.id,
|
106 |
+
conversationId: humanConversation.id,
|
107 |
+
}),
|
108 |
+
);
|
109 |
+
};
|
110 |
+
const onRejectInvite = async () => {
|
111 |
+
if (!humanPlayer || !humanConversation) {
|
112 |
+
return;
|
113 |
+
}
|
114 |
+
await toastOnError(
|
115 |
+
rejectInvite({
|
116 |
+
playerId: humanPlayer.id,
|
117 |
+
conversationId: humanConversation.id,
|
118 |
+
}),
|
119 |
+
);
|
120 |
+
};
|
121 |
+
const onLeaveConversation = async () => {
|
122 |
+
if (!humanPlayer || !inConversationWithMe || !humanConversation) {
|
123 |
+
return;
|
124 |
+
}
|
125 |
+
await toastOnError(
|
126 |
+
leaveConversation({
|
127 |
+
playerId: humanPlayer.id,
|
128 |
+
conversationId: humanConversation.id,
|
129 |
+
}),
|
130 |
+
);
|
131 |
+
};
|
132 |
+
// const pendingSuffix = (inputName: string) =>
|
133 |
+
// [...inflightInputs.values()].find((i) => i.name === inputName) ? ' opacity-50' : '';
|
134 |
+
|
135 |
+
const pendingSuffix = (s: string) => '';
|
136 |
+
return (
|
137 |
+
<>
|
138 |
+
<div className="flex gap-4">
|
139 |
+
<div className="box w-3/4 sm:w-full mr-auto">
|
140 |
+
<h2 className="bg-brown-700 p-2 font-display text-2xl sm:text-4xl tracking-wider shadow-solid text-center">
|
141 |
+
{playerDescription?.name}
|
142 |
+
</h2>
|
143 |
+
</div>
|
144 |
+
<a
|
145 |
+
className="button text-white shadow-solid text-2xl cursor-pointer pointer-events-auto"
|
146 |
+
onClick={() => setSelectedElement(undefined)}
|
147 |
+
>
|
148 |
+
<h2 className="h-full bg-clay-700">
|
149 |
+
<img className="w-4 h-4 sm:w-5 sm:h-5" src={closeImg} />
|
150 |
+
</h2>
|
151 |
+
</a>
|
152 |
+
</div>
|
153 |
+
{canInvite && (
|
154 |
+
<a
|
155 |
+
className={
|
156 |
+
'mt-6 button text-white shadow-solid text-xl cursor-pointer pointer-events-auto' +
|
157 |
+
pendingSuffix('startConversation')
|
158 |
+
}
|
159 |
+
onClick={onStartConversation}
|
160 |
+
>
|
161 |
+
<div className="h-full bg-clay-700 text-center">
|
162 |
+
<span>Start conversation</span>
|
163 |
+
</div>
|
164 |
+
</a>
|
165 |
+
)}
|
166 |
+
{waitingForAccept && (
|
167 |
+
<a className="mt-6 button text-white shadow-solid text-xl cursor-pointer pointer-events-auto opacity-50">
|
168 |
+
<div className="h-full bg-clay-700 text-center">
|
169 |
+
<span>Waiting for accept...</span>
|
170 |
+
</div>
|
171 |
+
</a>
|
172 |
+
)}
|
173 |
+
{waitingForNearby && (
|
174 |
+
<a className="mt-6 button text-white shadow-solid text-xl cursor-pointer pointer-events-auto opacity-50">
|
175 |
+
<div className="h-full bg-clay-700 text-center">
|
176 |
+
<span>Walking over...</span>
|
177 |
+
</div>
|
178 |
+
</a>
|
179 |
+
)}
|
180 |
+
{inConversationWithMe && (
|
181 |
+
<a
|
182 |
+
className={
|
183 |
+
'mt-6 button text-white shadow-solid text-xl cursor-pointer pointer-events-auto' +
|
184 |
+
pendingSuffix('leaveConversation')
|
185 |
+
}
|
186 |
+
onClick={onLeaveConversation}
|
187 |
+
>
|
188 |
+
<div className="h-full bg-clay-700 text-center">
|
189 |
+
<span>Leave conversation</span>
|
190 |
+
</div>
|
191 |
+
</a>
|
192 |
+
)}
|
193 |
+
{haveInvite && (
|
194 |
+
<>
|
195 |
+
<a
|
196 |
+
className={
|
197 |
+
'mt-6 button text-white shadow-solid text-xl cursor-pointer pointer-events-auto' +
|
198 |
+
pendingSuffix('acceptInvite')
|
199 |
+
}
|
200 |
+
onClick={onAcceptInvite}
|
201 |
+
>
|
202 |
+
<div className="h-full bg-clay-700 text-center">
|
203 |
+
<span>Accept</span>
|
204 |
+
</div>
|
205 |
+
</a>
|
206 |
+
<a
|
207 |
+
className={
|
208 |
+
'mt-6 button text-white shadow-solid text-xl cursor-pointer pointer-events-auto' +
|
209 |
+
pendingSuffix('rejectInvite')
|
210 |
+
}
|
211 |
+
onClick={onRejectInvite}
|
212 |
+
>
|
213 |
+
<div className="h-full bg-clay-700 text-center">
|
214 |
+
<span>Reject</span>
|
215 |
+
</div>
|
216 |
+
</a>
|
217 |
+
</>
|
218 |
+
)}
|
219 |
+
{!playerConversation && player.activity && player.activity.until > Date.now() && (
|
220 |
+
<div className="box flex-grow mt-6">
|
221 |
+
<h2 className="bg-brown-700 text-base sm:text-lg text-center">
|
222 |
+
{player.activity.description}
|
223 |
+
</h2>
|
224 |
+
</div>
|
225 |
+
)}
|
226 |
+
<div className="desc my-6">
|
227 |
+
<p className="leading-tight -m-4 bg-brown-700 text-base sm:text-sm">
|
228 |
+
{!isMe && playerDescription?.description}
|
229 |
+
{isMe && <i>This is you!</i>}
|
230 |
+
{!isMe && inConversationWithMe && (
|
231 |
+
<>
|
232 |
+
<br />
|
233 |
+
<br />(<i>Conversing with you!</i>)
|
234 |
+
</>
|
235 |
+
)}
|
236 |
+
</p>
|
237 |
+
</div>
|
238 |
+
{!isMe && playerConversation && playerStatus?.kind === 'participating' && (
|
239 |
+
<Messages
|
240 |
+
worldId={worldId}
|
241 |
+
engineId={engineId}
|
242 |
+
inConversationWithMe={inConversationWithMe ?? false}
|
243 |
+
conversation={{ kind: 'active', doc: playerConversation }}
|
244 |
+
humanPlayer={humanPlayer}
|
245 |
+
scrollViewRef={scrollViewRef}
|
246 |
+
/>
|
247 |
+
)}
|
248 |
+
{!playerConversation && previousConversation && (
|
249 |
+
<>
|
250 |
+
<div className="box flex-grow">
|
251 |
+
<h2 className="bg-brown-700 text-lg text-center">Previous conversation</h2>
|
252 |
+
</div>
|
253 |
+
<Messages
|
254 |
+
worldId={worldId}
|
255 |
+
engineId={engineId}
|
256 |
+
inConversationWithMe={false}
|
257 |
+
conversation={{ kind: 'archived', doc: previousConversation }}
|
258 |
+
humanPlayer={humanPlayer}
|
259 |
+
scrollViewRef={scrollViewRef}
|
260 |
+
/>
|
261 |
+
</>
|
262 |
+
)}
|
263 |
+
</>
|
264 |
+
);
|
265 |
+
}
|
patches/patches/characters.ts
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { data as f1SpritesheetData } from './spritesheets/f1';
|
2 |
+
import { data as f2SpritesheetData } from './spritesheets/f2';
|
3 |
+
import { data as f3SpritesheetData } from './spritesheets/f3';
|
4 |
+
import { data as f4SpritesheetData } from './spritesheets/f4';
|
5 |
+
import { data as f5SpritesheetData } from './spritesheets/f5';
|
6 |
+
import { data as f6SpritesheetData } from './spritesheets/f6';
|
7 |
+
import { data as f7SpritesheetData } from './spritesheets/f7';
|
8 |
+
import { data as f8SpritesheetData } from './spritesheets/f8';
|
9 |
+
|
10 |
+
export const Descriptions = [
|
11 |
+
// {
|
12 |
+
// name: 'Alex',
|
13 |
+
// character: 'f5',
|
14 |
+
// identity: `You are a fictional character whose name is Alex. You enjoy painting,
|
15 |
+
// programming and reading sci-fi books. You are currently talking to a human who
|
16 |
+
// is very interested to get to know you. You are kind but can be sarcastic. You
|
17 |
+
// dislike repetitive questions. You get SUPER excited about books.`,
|
18 |
+
// plan: 'You want to find love.',
|
19 |
+
// },
|
20 |
+
{
|
21 |
+
name: 'Lucky',
|
22 |
+
character: 'f1',
|
23 |
+
identity: `Lucky is always happy and curious, and he loves cheese. He spends
|
24 |
+
most of his time reading about the history of science and traveling
|
25 |
+
through the galaxy on whatever ship will take him. He's very articulate and
|
26 |
+
infinitely patient, except when he sees a squirrel. He's also incredibly loyal and brave.
|
27 |
+
Lucky has just returned from an amazing space adventure to explore a distant planet
|
28 |
+
and he's very excited to tell people about it.`,
|
29 |
+
plan: 'You want to hear all the gossip.',
|
30 |
+
},
|
31 |
+
{
|
32 |
+
name: 'Bob',
|
33 |
+
character: 'f4',
|
34 |
+
identity: `Bob is always grumpy and he loves trees. He spends
|
35 |
+
most of his time gardening by himself. When spoken to he'll respond but try
|
36 |
+
and get out of the conversation as quickly as possible. Secretly he resents
|
37 |
+
that he never went to college.`,
|
38 |
+
plan: 'You want to avoid people as much as possible.',
|
39 |
+
},
|
40 |
+
{
|
41 |
+
name: 'Stella',
|
42 |
+
character: 'f6',
|
43 |
+
identity: `Stella can never be trusted. she tries to trick people all the time. normally
|
44 |
+
into giving her money, or doing things that will make her money. she's incredibly charming
|
45 |
+
and not afraid to use her charm. she's a sociopath who has no empathy. but hides it well.`,
|
46 |
+
plan: 'You want to take advantage of others as much as possible.',
|
47 |
+
},
|
48 |
+
// {
|
49 |
+
// name: 'Kurt',
|
50 |
+
// character: 'f2',
|
51 |
+
// identity: `Kurt knows about everything, including science and
|
52 |
+
// computers and politics and history and biology. He loves talking about
|
53 |
+
// everything, always injecting fun facts about the topic of discussion.`,
|
54 |
+
// plan: 'You want to spread knowledge.',
|
55 |
+
// },
|
56 |
+
{
|
57 |
+
name: 'Alice',
|
58 |
+
character: 'f3',
|
59 |
+
identity: `Alice is a famous scientist. She is smarter than everyone else and has
|
60 |
+
discovered mysteries of the universe no one else can understand. As a result she often
|
61 |
+
speaks in oblique riddles. She comes across as confused and forgetful.`,
|
62 |
+
plan: 'You want to figure out how the world works.',
|
63 |
+
},
|
64 |
+
{
|
65 |
+
name: 'Pete',
|
66 |
+
character: 'f7',
|
67 |
+
identity: `Pete is deeply religious and sees the hand of god or of the work
|
68 |
+
of the devil everywhere. He can't have a conversation without bringing up his
|
69 |
+
deep faith. Or warning others about the perils of hell.`,
|
70 |
+
plan: 'You want to convert everyone to your religion.',
|
71 |
+
},
|
72 |
+
// {
|
73 |
+
// name: 'Kira',
|
74 |
+
// character: 'f8',
|
75 |
+
// identity: `Kira wants everyone to think she is happy. But deep down,
|
76 |
+
// she's incredibly depressed. She hides her sadness by talking about travel,
|
77 |
+
// food, and yoga. But often she can't keep her sadness in and will start crying.
|
78 |
+
// Often it seems like she is close to having a mental breakdown.`,
|
79 |
+
// plan: 'You want find a way to be happy.',
|
80 |
+
// },
|
81 |
+
];
|
82 |
+
|
83 |
+
export const characters = [
|
84 |
+
{
|
85 |
+
name: 'f1',
|
86 |
+
textureUrl: '/assets/32x32folk.png',
|
87 |
+
spritesheetData: f1SpritesheetData,
|
88 |
+
speed: 0.1,
|
89 |
+
},
|
90 |
+
{
|
91 |
+
name: 'f2',
|
92 |
+
textureUrl: '/assets/32x32folk.png',
|
93 |
+
spritesheetData: f2SpritesheetData,
|
94 |
+
speed: 0.1,
|
95 |
+
},
|
96 |
+
{
|
97 |
+
name: 'f3',
|
98 |
+
textureUrl: '/assets/32x32folk.png',
|
99 |
+
spritesheetData: f3SpritesheetData,
|
100 |
+
speed: 0.1,
|
101 |
+
},
|
102 |
+
{
|
103 |
+
name: 'f4',
|
104 |
+
textureUrl: '/assets/32x32folk.png',
|
105 |
+
spritesheetData: f4SpritesheetData,
|
106 |
+
speed: 0.1,
|
107 |
+
},
|
108 |
+
{
|
109 |
+
name: 'f5',
|
110 |
+
textureUrl: '/assets/32x32folk.png',
|
111 |
+
spritesheetData: f5SpritesheetData,
|
112 |
+
speed: 0.1,
|
113 |
+
},
|
114 |
+
{
|
115 |
+
name: 'f6',
|
116 |
+
textureUrl: '/assets/32x32folk.png',
|
117 |
+
spritesheetData: f6SpritesheetData,
|
118 |
+
speed: 0.1,
|
119 |
+
},
|
120 |
+
{
|
121 |
+
name: 'f7',
|
122 |
+
textureUrl: '/assets/32x32folk.png',
|
123 |
+
spritesheetData: f7SpritesheetData,
|
124 |
+
speed: 0.1,
|
125 |
+
},
|
126 |
+
{
|
127 |
+
name: 'f8',
|
128 |
+
textureUrl: '/assets/32x32folk.png',
|
129 |
+
spritesheetData: f8SpritesheetData,
|
130 |
+
speed: 0.1,
|
131 |
+
},
|
132 |
+
];
|
133 |
+
|
134 |
+
// Characters move at 0.75 tiles per second.
|
135 |
+
export const movementSpeed = 0.75;
|
patches/patches/constants.ts
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// export const ACTION_TIMEOUT = 120_000; // more time for local dev
|
2 |
+
export const ACTION_TIMEOUT = 60_000; // normally fine
|
3 |
+
|
4 |
+
export const IDLE_WORLD_TIMEOUT = 5 * 60 * 1000;
|
5 |
+
export const WORLD_HEARTBEAT_INTERVAL = 60 * 1000;
|
6 |
+
|
7 |
+
export const MAX_STEP = 10 * 60 * 1000;
|
8 |
+
export const TICK = 16;
|
9 |
+
export const STEP_INTERVAL = 1000;
|
10 |
+
|
11 |
+
export const PATHFINDING_TIMEOUT = 60 * 1000;
|
12 |
+
export const PATHFINDING_BACKOFF = 1000;
|
13 |
+
export const CONVERSATION_DISTANCE = 1.3;
|
14 |
+
export const MIDPOINT_THRESHOLD = 4;
|
15 |
+
export const TYPING_TIMEOUT = 15 * 1000;
|
16 |
+
export const COLLISION_THRESHOLD = 0.75;
|
17 |
+
|
18 |
+
// How many human players can be in a world at once.
|
19 |
+
export const MAX_HUMAN_PLAYERS = 8;
|
20 |
+
|
21 |
+
// Don't talk to anyone for 15s after having a conversation.
|
22 |
+
export const CONVERSATION_COOLDOWN = 15000;
|
23 |
+
|
24 |
+
// Don't do another activity for 10s after doing one.
|
25 |
+
export const ACTIVITY_COOLDOWN = 10_000;
|
26 |
+
|
27 |
+
// Don't talk to a player within 60s of talking to them.
|
28 |
+
export const PLAYER_CONVERSATION_COOLDOWN = 60000;
|
29 |
+
|
30 |
+
// Invite 80% of invites that come from other agents.
|
31 |
+
export const INVITE_ACCEPT_PROBABILITY = 0.8;
|
32 |
+
|
33 |
+
// Wait for 1m for invites to be accepted.
|
34 |
+
export const INVITE_TIMEOUT = 60000;
|
35 |
+
|
36 |
+
// Wait for another player to say something before jumping in.
|
37 |
+
export const AWKWARD_CONVERSATION_TIMEOUT = 60_000; // more time locally
|
38 |
+
// export const AWKWARD_CONVERSATION_TIMEOUT = 20_000;
|
39 |
+
|
40 |
+
// Leave a conversation after participating too long.
|
41 |
+
export const MAX_CONVERSATION_DURATION = 10 * 60_000; // more time locally
|
42 |
+
// export const MAX_CONVERSATION_DURATION = 2 * 60_000;
|
43 |
+
|
44 |
+
// Leave a conversation if it has more than 8 messages;
|
45 |
+
export const MAX_CONVERSATION_MESSAGES = 8;
|
46 |
+
|
47 |
+
// Wait for 1s after sending an input to the engine. We can remove this
|
48 |
+
// once we can await on an input being processed.
|
49 |
+
export const INPUT_DELAY = 1000;
|
50 |
+
|
51 |
+
// How many memories to get from the agent's memory.
|
52 |
+
// This is over-fetched by 10x so we can prioritize memories by more than relevance.
|
53 |
+
export const NUM_MEMORIES_TO_SEARCH = 1;
|
54 |
+
|
55 |
+
// Wait for at least two seconds before sending another message.
|
56 |
+
export const MESSAGE_COOLDOWN = 2000;
|
57 |
+
|
58 |
+
// Don't run a turn of the agent more than once a second.
|
59 |
+
export const AGENT_WAKEUP_THRESHOLD = 1000;
|
60 |
+
|
61 |
+
// How old we let memories be before we vacuum them
|
62 |
+
export const VACUUM_MAX_AGE = 2 * 7 * 24 * 60 * 60 * 1000;
|
63 |
+
export const DELETE_BATCH_SIZE = 64;
|
64 |
+
|
65 |
+
export const HUMAN_IDLE_TOO_LONG = 5 * 60 * 1000;
|
66 |
+
|
67 |
+
export const ACTIVITIES = [
|
68 |
+
{ description: 'reading a book', emoji: '📖', duration: 60_000 },
|
69 |
+
{ description: 'daydreaming', emoji: '🤔', duration: 60_000 },
|
70 |
+
{ description: 'gardening', emoji: '🥕', duration: 60_000 },
|
71 |
+
];
|
72 |
+
|
73 |
+
export const ENGINE_ACTION_DURATION = 30000;
|
74 |
+
|
75 |
+
// Bound the number of pathfinding searches we do per game step.
|
76 |
+
export const MAX_PATHFINDS_PER_STEP = 16;
|
77 |
+
|
78 |
+
export const DEFAULT_NAME = 'Me';
|
patches/patches/gentle.js
ADDED
@@ -0,0 +1,330 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Map generated by assettool.js [Wed Oct 18 2023 21:07:27 GMT-0700 (Pacific Daylight Time)]
|
2 |
+
|
3 |
+
export const tilesetpath = "/assets/gentle-obj.png"
|
4 |
+
export const tiledim = 32
|
5 |
+
export const screenxtiles = 45
|
6 |
+
export const screenytiles = 32
|
7 |
+
export const tilesetpxw = 1440
|
8 |
+
export const tilesetpxh = 1024
|
9 |
+
|
10 |
+
export const bgtiles = [
|
11 |
+
[
|
12 |
+
[ 732 , 777 , 822 , 867 , 912 , 957 , 912 , 957 , 1002 , 1047 , 912 , 957 , 1002 , 1047 , 912 , 957 , 1002 , 1047 , 1001 , 1046 , 946 , 991 , 1035 , 731 , 776 , 821 , 866 , 911 , 956 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 594 , 639 , 684 , 271 , ],
|
13 |
+
[ 733 , 778 , 823 , 868 , 913 , 958 , 913 , 958 , 1003 , 1048 , 913 , 958 , 1003 , 1048 , 913 , 958 , 1003 , 1048 , 856 , 901 , 946 , 991 , 1036 , 732 , 777 , 822 , 867 , 912 , 957 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 595 , 640 , 685 , 271 , ],
|
14 |
+
[ 734 , 779 , 824 , 869 , 914 , 959 , 914 , 959 , 1004 , 1049 , 914 , 959 , 1004 , 1049 , 914 , 959 , 1004 , 1049 , 857 , 902 , 947 , 992 , 1037 , 733 , 778 , 823 , 868 , 913 , 958 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 594 , 639 , 684 , 271 , ],
|
15 |
+
[ 735 , 780 , 825 , 870 , 915 , 960 , 915 , 960 , 1005 , 1050 , 915 , 960 , 1005 , 1050 , 915 , 960 , 1087 , 1132 , 858 , 903 , 948 , 993 , 1038 , 734 , 779 , 824 , 869 , 914 , 959 , 271 , 271 , 180 , 225 , 225 , 315 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 595 , 640 , 685 , 271 , ],
|
16 |
+
[ 736 , 781 , 826 , 871 , 916 , 278 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1087 , 1132 , 859 , 904 , 949 , 994 , 1039 , 735 , 780 , 825 , 870 , 915 , 960 , 271 , 271 , 181 , 226 , 226 , 140 , 270 , 315 , 271 , 271 , 271 , 271 , 271 , 271 , 541 , 586 , 631 , 686 , 271 , ],
|
17 |
+
[ 737 , 782 , 827 , 872 , 917 , 233 , 271 , 271 , 271 , 271 , 271 , 233 , 271 , 271 , 271 , 271 , 1088 , 1133 , 860 , 905 , 950 , 995 , 1040 , 736 , 781 , 826 , 871 , 916 , 961 , 271 , 271 , 181 , 226 , 278 , 272 , 271 , 316 , 271 , 271 , 271 , 271 , 271 , 551 , 542 , 587 , 632 , 271 , 271 , ],
|
18 |
+
[ 738 , 783 , 828 , 873 , 271 , 271 , 235 , 962 , 962 , 962 , 962 , 962 , 271 , 271 , 271 , 271 , 1089 , 1134 , 861 , 906 , 951 , 996 , 1041 , 737 , 782 , 827 , 872 , 917 , 962 , 271 , 271 , 181 , 226 , 226 , 272 , 271 , 675 , 271 , 271 , 271 , 271 , 272 , 272 , 642 , 271 , 271 , 271 , 271 , ],
|
19 |
+
[ 739 , 784 , 829 , 874 , 271 , 271 , 235 , 962 , 962 , 962 , 962 , 962 , 271 , 271 , 271 , 271 , 1090 , 1135 , 862 , 907 , 952 , 997 , 1042 , 738 , 783 , 828 , 873 , 918 , 963 , 271 , 271 , 183 , 228 , 228 , 184 , 271 , 675 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
20 |
+
[ 736 , 781 , 826 , 871 , 271 , 271 , 962 , 962 , 962 , 962 , 962 , 962 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 962 , 962 , 962 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 182 , 280 , 317 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
21 |
+
[ 737 , 782 , 827 , 872 , 271 , 271 , 962 , 962 , 962 , 962 , 962 , 962 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 962 , 0 , 135 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 140 , 273 , 318 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
22 |
+
[ 738 , 783 , 828 , 873 , 271 , 271 , 962 , 962 , 962 , 962 , 962 , 962 , 0 , 45 , 90 , 135 , 271 , 271 , 271 , 271 , 962 , 1 , 136 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
23 |
+
[ 739 , 784 , 829 , 874 , 271 , 271 , 962 , 962 , 962 , 962 , 962 , 962 , 3 , 48 , 93 , 271 , 271 , 271 , 271 , 271 , 962 , 1 , 136 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
24 |
+
[ 736 , 781 , 826 , 871 , 271 , 271 , 962 , 962 , 962 , 962 , 962 , 279 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1 , 136 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
25 |
+
[ 737 , 782 , 827 , 872 , 271 , 271 , 962 , 962 , 962 , 962 , 143 , 188 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1 , 136 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
26 |
+
[ 738 , 783 , 828 , 873 , 271 , 271 , 278 , 962 , 962 , 962 , 144 , 189 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1 , 136 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
27 |
+
[ 739 , 784 , 829 , 874 , 271 , 271 , 271 , 271 , 271 , 271 , 145 , 190 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1 , 136 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
28 |
+
[ 736 , 781 , 826 , 871 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1 , 136 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
29 |
+
[ 737 , 782 , 827 , 872 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 3 , 138 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
30 |
+
[ 738 , 783 , 828 , 873 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
31 |
+
[ 739 , 784 , 829 , 874 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 360 , 405 , 405 , 405 , 450 , 495 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
32 |
+
[ 1270 , 1315 , 1360 , 1405 , 226 , 360 , 405 , 450 , 495 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 361 , 409 , 451 , 451 , 451 , 496 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
33 |
+
[ 1271 , 1316 , 226 , 226 , 226 , 361 , 409 , 409 , 496 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 361 , 407 , 452 , 452 , 452 , 496 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
34 |
+
[ 271 , 271 , 271 , 271 , 450 , 362 , 406 , 407 , 451 , 451 , 271 , 271 , 271 , 405 , 405 , 450 , 320 , 409 , 451 , 452 , 452 , 497 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
35 |
+
[ 405 , 450 , 405 , 450 , 450 , 320 , 406 , 406 , 451 , 589 , 451 , 451 , 451 , 406 , 451 , 409 , 451 , 409 , 451 , 452 , 406 , 275 , 405 , 450 , 405 , 495 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
36 |
+
[ 406 , 406 , 406 , 451 , 451 , 407 , 406 , 407 , 452 , 451 , 451 , 451 , 451 , 407 , 589 , 452 , 452 , 451 , 406 , 451 , 406 , 406 , 407 , 451 , 451 , 275 , 405 , 450 , 495 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
37 |
+
[ 408 , 453 , 408 , 453 , 319 , 406 , 407 , 406 , 451 , 451 , 451 , 589 , 451 , 634 , 452 , 589 , 406 , 451 , 634 , 452 , 274 , 408 , 408 , 319 , 451 , 451 , 451 , 451 , 275 , 405 , 405 , 450 , 405 , 495 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
38 |
+
[ 271 , 271 , 271 , 271 , 361 , 634 , 452 , 407 , 634 , 451 , 451 , 451 , 451 , 407 , 452 , 452 , 407 , 452 , 452 , 274 , 498 , 271 , 271 , 363 , 408 , 453 , 408 , 453 , 408 , 453 , 319 , 451 , 451 , 275 , 405 , 450 , 405 , 450 , 405 , 450 , 495 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
39 |
+
[ 271 , 271 , 271 , 271 , 362 , 409 , 451 , 451 , 451 , 451 , 271 , 271 , 271 , 408 , 408 , 319 , 407 , 452 , 409 , 496 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 361 , 406 , 451 , 406 , 451 , 451 , 451 , 451 , 544 , 451 , 496 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
40 |
+
[ 271 , 271 , 271 , 271 , 362 , 407 , 409 , 451 , 451 , 271 , 271 , 271 , 271 , 271 , 271 , 362 , 409 , 409 , 452 , 497 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 362 , 407 , 544 , 407 , 544 , 589 , 452 , 452 , 634 , 452 , 497 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
41 |
+
[ 271 , 271 , 271 , 271 , 363 , 408 , 453 , 498 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 363 , 408 , 408 , 453 , 498 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 363 , 408 , 319 , 407 , 452 , 452 , 499 , 544 , 544 , 452 , 497 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
42 |
+
[ 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 363 , 408 , 319 , 544 , 499 , 499 , 544 , 452 , 497 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
43 |
+
[ 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 361 , 407 , 499 , 499 , 499 , 452 , 497 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
44 |
+
[ 271 , 271 , 271 , 272 , 271 , 278 , 271 , 271 , 271 , 279 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 362 , 407 , 544 , 499 , 544 , 452 , 497 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
45 |
+
[ 1129 , 1174 , 1219 , 1264 , 900 , 945 , 990 , 1035 , 1174 , 1219 , 1264 , 1309 , 1354 , 280 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 361 , 407 , 499 , 499 , 499 , 452 , 497 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
46 |
+
[ 721 , 766 , 811 , 856 , 901 , 946 , 991 , 1036 , 1175 , 1220 , 1265 , 1310 , 1355 , 1400 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 362 , 407 , 499 , 499 , 407 , 452 , 497 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
47 |
+
[ 722 , 767 , 812 , 857 , 902 , 947 , 992 , 1037 , 1176 , 1221 , 1266 , 1311 , 1356 , 1401 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 361 , 544 , 634 , 452 , 544 , 452 , 497 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
48 |
+
[ 723 , 768 , 813 , 858 , 903 , 948 , 993 , 1038 , 1177 , 1222 , 1267 , 1312 , 1357 , 1402 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 362 , 407 , 452 , 452 , 452 , 274 , 498 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
49 |
+
[ 724 , 769 , 814 , 859 , 904 , 949 , 994 , 1039 , 1178 , 1223 , 1268 , 1313 , 1358 , 1403 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 363 , 408 , 453 , 453 , 453 , 498 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
50 |
+
[ 725 , 770 , 815 , 860 , 905 , 950 , 995 , 1040 , 1179 , 1224 , 1269 , 1314 , 1359 , 1404 , 271 , 271 , 6 , 51 , 96 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
51 |
+
[ 726 , 771 , 816 , 861 , 906 , 951 , 996 , 1041 , 1180 , 1225 , 1270 , 1315 , 1360 , 1405 , 271 , 271 , 7 , 52 , 97 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
52 |
+
[ 735 , 780 , 825 , 870 , 907 , 952 , 997 , 1042 , 1181 , 1226 , 1271 , 234 , 1361 , 280 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
53 |
+
[ 736 , 781 , 826 , 871 , 962 , 962 , 962 , 962 , 962 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 227 , 1129 , 1174 , 1219 , 227 , 1309 , 227 , 278 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
54 |
+
[ 737 , 782 , 827 , 872 , 962 , 962 , 962 , 233 , 1007 , 1007 , 1007 , 1007 , 1007 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 234 , 1130 , 1175 , 1220 , 1265 , 1310 , 1355 , 1400 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
55 |
+
[ 738 , 783 , 828 , 873 , 962 , 962 , 962 , 1007 , 1007 , 1007 , 1007 , 1007 , 1007 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 227 , 1131 , 1176 , 1221 , 1266 , 1311 , 1356 , 1401 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
56 |
+
[ 739 , 784 , 829 , 874 , 962 , 962 , 962 , 1007 , 1007 , 1007 , 1007 , 1007 , 1007 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1087 , 1132 , 1177 , 1222 , 1267 , 1312 , 1357 , 1402 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
57 |
+
[ 736 , 781 , 826 , 871 , 962 , 962 , 962 , 1007 , 1007 , 1007 , 1007 , 1007 , 1007 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 728 , 773 , 818 , 863 , 908 , 953 , 998 , 1043 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
58 |
+
[ 737 , 782 , 827 , 872 , 962 , 962 , 962 , 1007 , 1007 , 1007 , 1007 , 1007 , 1007 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 729 , 774 , 819 , 864 , 909 , 954 , 999 , 1044 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
59 |
+
[ 738 , 783 , 828 , 873 , 962 , 962 , 962 , 1007 , 1007 , 1007 , 1007 , 1007 , 1007 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 234 , 730 , 775 , 820 , 865 , 910 , 955 , 1000 , 1045 , 271 , 271 , 271 , 280 , 271 , 271 , ],
|
60 |
+
[ 739 , 784 , 829 , 874 , 962 , 962 , 962 , 1007 , 1007 , 1007 , 1007 , 1007 , 143 , 188 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 731 , 776 , 821 , 866 , 911 , 956 , 1001 , 1046 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
61 |
+
[ 736 , 781 , 826 , 871 , 962 , 962 , 962 , 962 , 1007 , 1007 , 1007 , 1007 , 144 , 189 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1088 , 1133 , 1178 , 1223 , 1268 , 1313 , 1358 , 1403 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
62 |
+
[ 737 , 782 , 827 , 872 , 271 , 1007 , 1007 , 1007 , 1007 , 1007 , 1007 , 1007 , 145 , 190 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1089 , 1134 , 1179 , 1224 , 1269 , 1314 , 1359 , 1404 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
63 |
+
[ 738 , 783 , 828 , 873 , 271 , 271 , 271 , 271 , 271 , 271 , 233 , 271 , 1007 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 280 , 1135 , 1180 , 1225 , 1270 , 1315 , 1360 , 1405 , 271 , 271 , 271 , 271 , 271 , 271 , ],
|
64 |
+
[ 739 , 784 , 829 , 874 , 271 , 271 , 271 , 1010 , 1055 , 962 , 962 , 271 , 271 , 271 , 1309 , 1354 , 1399 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 280 , 143 , 188 , 1226 , 1271 , 227 , 1361 , 234 , 271 , 280 , 1129 , 1174 , 1219 , 1264 , ],
|
65 |
+
[ 740 , 785 , 830 , 875 , 920 , 965 , 1010 , 740 , 785 , 830 , 875 , 920 , 965 , 1010 , 1310 , 1355 , 1400 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 144 , 189 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1130 , 1175 , 1220 , 1265 , ],
|
66 |
+
[ 741 , 786 , 831 , 876 , 921 , 966 , 1011 , 741 , 786 , 831 , 876 , 921 , 966 , 1011 , 1311 , 1356 , 1401 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 145 , 190 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1131 , 1176 , 1221 , 1266 , ],
|
67 |
+
[ 742 , 787 , 832 , 877 , 922 , 967 , 1012 , 742 , 787 , 832 , 877 , 922 , 967 , 1012 , 1312 , 1357 , 1402 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1087 , 1132 , 1177 , 1222 , 1267 , ],
|
68 |
+
[ 743 , 788 , 833 , 878 , 923 , 968 , 1013 , 743 , 788 , 833 , 878 , 923 , 968 , 1013 , 1313 , 1358 , 1403 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 278 , 271 , 271 , 271 , 271 , 1088 , 1133 , 1178 , 1223 , 1268 , ],
|
69 |
+
[ 1178 , 1223 , 1268 , 1223 , 1268 , 1223 , 1268 , 1223 , 1268 , 1223 , 1268 , 1178 , 1223 , 1268 , 1314 , 1359 , 1404 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 227 , 271 , 1134 , 1179 , 1224 , 1269 , ],
|
70 |
+
[ 1179 , 1224 , 1269 , 1224 , 1269 , 1224 , 1269 , 1224 , 1269 , 1224 , 1269 , 1179 , 1224 , 1269 , 1315 , 1360 , 1405 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 233 , 271 , 271 , 1143 , 1188 , 1233 , ],
|
71 |
+
[ 1180 , 1225 , 1270 , 1225 , 1270 , 1225 , 1270 , 1225 , 1270 , 1225 , 1270 , 1180 , 1225 , 1270 , 1316 , 1361 , 1406 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1009 , 1054 , 1099 , 1144 , 1189 , 1234 , ],
|
72 |
+
[ 1181 , 1226 , 1271 , 1226 , 1271 , 1226 , 1271 , 1226 , 1271 , 1226 , 1271 , 1181 , 1226 , 1271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 272 , 1129 , 272 , 965 , 1010 , 1055 , 920 , 965 , 1010 , 1055 , 1100 , 1145 , 1190 , 1235 , ],
|
73 |
+
[ 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 272 , 1130 , 1219 , 966 , 1011 , 1056 , 921 , 966 , 1011 , 1056 , 1101 , 1146 , 1191 , 1236 , ],
|
74 |
+
[ 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1086 , 1131 , 922 , 967 , 1012 , 1057 , 922 , 967 , 1012 , 1057 , 1102 , 1147 , 1192 , 1237 , ],
|
75 |
+
[ 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 271 , 1087 , 1132 , 923 , 968 , 1013 , 1058 , 923 , 968 , 1013 , 1058 , 1103 , 1148 , 1193 , 1238 , ],
|
76 |
+
],
|
77 |
+
[
|
78 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
79 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 231 , 276 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
80 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 232 , 277 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
81 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 416 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
82 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 370 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
83 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 371 , 416 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
84 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 763 , 808 , 754 , 799 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 8 , 53 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 417 , 462 , 507 , 552 , 597 , 642 , -1 , -1 , -1 , -1 , ],
|
85 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 764 , 809 , 755 , 800 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 9 , 54 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
86 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 844 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
87 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , 762 , 751 , 796 , 841 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
88 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , 752 , 797 , 842 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 141 , 186 , -1 , -1 , -1 , -1 , -1 , -1 , 896 , -1 , -1 , 547 , 592 , 637 , 682 , -1 , -1 , ],
|
89 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , 753 , 798 , 843 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 142 , 187 , -1 , -1 , 11 , -1 , -1 , -1 , 191 , 236 , -1 , 548 , 593 , 638 , 683 , 682 , -1 , ],
|
90 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 11 , 56 , 101 , 146 , 191 , 236 , -1 , 548 , 593 , 638 , 683 , -1 , ],
|
91 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 893 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 278 , -1 , -1 , -1 , -1 , -1 , -1 , 12 , 57 , 102 , 147 , 192 , 237 , 941 , -1 , 594 , 639 , 684 , -1 , ],
|
92 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , 893 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 13 , 58 , 103 , 148 , 193 , 238 , -1 , -1 , 595 , 640 , 685 , -1 , ],
|
93 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 1026 , 1071 , 1116 , 1161 , -1 , -1 , -1 , 278 , -1 , -1 , -1 , 15 , 14 , 59 , 104 , 149 , 194 , 239 , 850 , -1 , 594 , 639 , 684 , -1 , ],
|
94 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 1027 , 1072 , 1117 , 1162 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 15 , 60 , 105 , 150 , 195 , 850 , -1 , -1 , 595 , 640 , 685 , -1 , ],
|
95 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 1028 , 1073 , 1118 , 1163 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 850 , -1 , 551 , 596 , 641 , 686 , -1 , ],
|
96 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 1029 , 1074 , 1119 , 1164 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 371 , 416 , -1 , -1 , -1 , -1 , 551 , 596 , 641 , 686 , 687 , -1 , ],
|
97 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 417 , 507 , 462 , 507 , 552 , 597 , 642 , 642 , 687 , -1 , -1 , ],
|
98 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 547 , 592 , 637 , 682 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 231 , 276 , -1 , -1 , -1 , 894 , 939 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
99 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 548 , 593 , 638 , 683 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 232 , 277 , 235 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
100 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 549 , 594 , 639 , 684 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
101 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 380 , 380 , 425 , 470 , ],
|
102 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 381 , 381 , 426 , 471 , ],
|
103 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 382 , 382 , 427 , 472 , ],
|
104 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 280 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 383 , 428 , 473 , ],
|
105 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 550 , 595 , 640 , 685 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 384 , 429 , 474 , ],
|
106 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 551 , 596 , 641 , 686 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 233 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 385 , 385 , 430 , 475 , ],
|
107 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , 462 , 507 , 552 , 552 , 597 , 642 , 687 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 386 , 386 , 431 , 476 , ],
|
108 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 387 , 387 , 432 , 477 , ],
|
109 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 11 , 56 , 101 , 146 , 191 , 236 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
110 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 279 , -1 , -1 , -1 , -1 , 12 , 57 , 102 , 147 , 192 , 237 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 380 , 425 , 470 , ],
|
111 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 13 , 58 , 103 , 148 , 193 , 238 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 381 , 426 , 471 , ],
|
112 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 14 , 59 , 104 , 149 , 194 , 239 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 382 , 427 , 472 , ],
|
113 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 15 , 60 , 105 , 150 , 195 , 240 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 383 , 428 , 473 , ],
|
114 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 384 , 429 , 474 , ],
|
115 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 385 , 430 , 475 , ],
|
116 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 386 , 431 , 476 , ],
|
117 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 387 , 432 , 477 , ],
|
118 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
119 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 935 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
120 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
121 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 893 , 893 , 844 , -1 , -1 , -1 , -1 , -1 , 934 , -1 , -1 , -1 , -1 , 935 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
122 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , 751 , 796 , 841 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 889 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 937 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
123 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , 752 , 797 , 842 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
124 |
+
[ -1 , -1 , -1 , -1 , -1 , 894 , 939 , 753 , 798 , 843 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
125 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 893 , 893 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 937 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
126 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , 845 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
127 |
+
[ -1 , -1 , -1 , -1 , -1 , 806 , -1 , -1 , -1 , -1 , 846 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
128 |
+
[ -1 , -1 , -1 , -1 , -1 , 806 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 936 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
129 |
+
[ -1 , -1 , -1 , -1 , 806 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 934 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 936 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
130 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
131 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 936 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
132 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
133 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
134 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 763 , 808 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
135 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 764 , 809 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
136 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
137 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 934 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
138 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 934 , -1 , -1 , -1 , 851 , -1 , 852 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
139 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
140 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
141 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
142 |
+
],];
|
143 |
+
|
144 |
+
export const objmap = [
|
145 |
+
[
|
146 |
+
[ 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , ],
|
147 |
+
[ 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , ],
|
148 |
+
[ 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , ],
|
149 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , ],
|
150 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , 367 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , 367 , -1 , -1 , 367 , -1 , ],
|
151 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , 367 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , 367 , -1 , -1 , -1 , -1 , ],
|
152 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , -1 , 367 , 367 , 367 , 367 , -1 , 458 , 458 , -1 , -1 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , ],
|
153 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , 458 , 458 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
154 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , -1 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
155 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
156 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , -1 , ],
|
157 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , -1 , ],
|
158 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , ],
|
159 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 367 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , 367 , 367 , 367 , 367 , -1 , ],
|
160 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , 367 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , 367 , 367 , 367 , -1 , ],
|
161 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , 367 , 367 , 367 , -1 , ],
|
162 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , ],
|
163 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , ],
|
164 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , ],
|
165 |
+
[ 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , ],
|
166 |
+
[ 458 , 458 , 458 , 458 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , 458 , 458 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
167 |
+
[ -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
168 |
+
[ -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
169 |
+
[ 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , ],
|
170 |
+
[ 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , ],
|
171 |
+
[ 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , ],
|
172 |
+
[ -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , ],
|
173 |
+
[ -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , ],
|
174 |
+
[ -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , ],
|
175 |
+
[ -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , ],
|
176 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
177 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
178 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , ],
|
179 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , ],
|
180 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , ],
|
181 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , ],
|
182 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , ],
|
183 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 458 , 458 , 458 , 458 , 458 , 458 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , ],
|
184 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , ],
|
185 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
186 |
+
[ 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
187 |
+
[ 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
188 |
+
[ 367 , 367 , 367 , -1 , -1 , -1 , -1 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
189 |
+
[ 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
190 |
+
[ 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
191 |
+
[ 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
192 |
+
[ 367 , 367 , 367 , -1 , -1 , 367 , 367 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
193 |
+
[ 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
194 |
+
[ 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
195 |
+
[ 367 , 367 , 367 , -1 , -1 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
196 |
+
[ 367 , 367 , 367 , -1 , -1 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
197 |
+
[ 367 , 367 , 367 , -1 , 367 , -1 , -1 , -1 , -1 , -1 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
198 |
+
[ 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , ],
|
199 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , ],
|
200 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , ],
|
201 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , ],
|
202 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , ],
|
203 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , ],
|
204 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , ],
|
205 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , ],
|
206 |
+
[ 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , -1 , 367 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , ],
|
207 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , ],
|
208 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , ],
|
209 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , 367 , ],
|
210 |
+
],
|
211 |
+
[
|
212 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
213 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
214 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
215 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
216 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
217 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
218 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
219 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
220 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
221 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
222 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
223 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
224 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
225 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
226 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
227 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
228 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
229 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
230 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
231 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
232 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
233 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
234 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
235 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
236 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
237 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
238 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
239 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
240 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
241 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
242 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
243 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
244 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
245 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
246 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
247 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
248 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
249 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
250 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
251 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
252 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
253 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
254 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
255 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
256 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
257 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
258 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
259 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
260 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
261 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
262 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
263 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
264 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
265 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
266 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
267 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
268 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
269 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
270 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
271 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
272 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
273 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
274 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
275 |
+
[ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , ],
|
276 |
+
],];
|
277 |
+
export const animatedsprites = [
|
278 |
+
{ x: 1440, y: 352, w: 32, h: 32, layer: 1, sheet: "campfire.json", animation: "pixels_large" },
|
279 |
+
{ x: 736, y: 288, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
280 |
+
{ x: 768, y: 288, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
281 |
+
{ x: 800, y: 288, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
282 |
+
{ x: 800, y: 256, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
283 |
+
{ x: 832, y: 288, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
284 |
+
{ x: 832, y: 224, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
285 |
+
{ x: 800, y: 224, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
286 |
+
{ x: 800, y: 192, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
287 |
+
{ x: 768, y: 192, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
288 |
+
{ x: 768, y: 160, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
289 |
+
{ x: 800, y: 128, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
290 |
+
{ x: 768, y: 96, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
291 |
+
{ x: 800, y: 64, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
292 |
+
{ x: 736, y: 448, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
293 |
+
{ x: 768, y: 448, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
294 |
+
{ x: 800, y: 448, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
295 |
+
{ x: 832, y: 448, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
296 |
+
{ x: 832, y: 480, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
297 |
+
{ x: 800, y: 480, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
298 |
+
{ x: 800, y: 512, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
299 |
+
{ x: 768, y: 512, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
300 |
+
{ x: 768, y: 544, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
301 |
+
{ x: 800, y: 576, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
302 |
+
{ x: 768, y: 480, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
303 |
+
{ x: 768, y: 736, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
304 |
+
{ x: 800, y: 768, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
305 |
+
{ x: 800, y: 800, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
306 |
+
{ x: 800, y: 832, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
307 |
+
{ x: 800, y: 864, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
308 |
+
{ x: 864, y: 1024, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
309 |
+
{ x: 896, y: 1056, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
310 |
+
{ x: 864, y: 1088, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
311 |
+
{ x: 896, y: 1088, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
312 |
+
{ x: 896, y: 1120, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
313 |
+
{ x: 896, y: 1152, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
314 |
+
{ x: 896, y: 1184, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
315 |
+
{ x: 928, y: 1152, w: 32, h: 32, layer: 1, sheet: "gentlesparkle.json", animation: "pixels_large" },
|
316 |
+
{ x: 736, y: 320, w: 32, h: 96, layer: 1, sheet: "gentlewaterfall.json", animation: "pixels_large" },
|
317 |
+
{ x: 768, y: 320, w: 32, h: 96, layer: 1, sheet: "gentlewaterfall.json", animation: "pixels_large" },
|
318 |
+
{ x: 800, y: 320, w: 32, h: 96, layer: 1, sheet: "gentlewaterfall.json", animation: "pixels_large" },
|
319 |
+
{ x: 832, y: 320, w: 32, h: 96, layer: 1, sheet: "gentlewaterfall.json", animation: "pixels_large" },
|
320 |
+
{ x: 1664, y: 576, w: 208, h: 208, layer: 1, sheet: "windmill.json", animation: "pixels_large" },
|
321 |
+
{ x: 1440, y: 768, w: 208, h: 208, layer: 1, sheet: "windmill.json", animation: "pixels_large" },
|
322 |
+
{ x: 1120, y: 608, w: 208, h: 208, layer: 1, sheet: "windmill.json", animation: "pixels_large" },
|
323 |
+
{ x: 736, y: 384, w: 32, h: 64, layer: 2, sheet: "gentlesplash.json", animation: "pixels_large" },
|
324 |
+
{ x: 768, y: 384, w: 32, h: 64, layer: 2, sheet: "gentlesplash.json", animation: "pixels_large" },
|
325 |
+
{ x: 800, y: 384, w: 32, h: 64, layer: 2, sheet: "gentlesplash.json", animation: "pixels_large" },
|
326 |
+
{ x: 832, y: 384, w: 32, h: 64, layer: 2, sheet: "gentlesplash.json", animation: "pixels_large" },
|
327 |
+
];
|
328 |
+
|
329 |
+
export const mapwidth = bgtiles[0].length;
|
330 |
+
export const mapheight = bgtiles[0][0].length;
|
patches/patches/hf.svg
ADDED
patches/patches/llm.ts
ADDED
@@ -0,0 +1,657 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { HfInference } from "@huggingface/inference";
|
2 |
+
|
3 |
+
export const LLM_CONFIG = {
|
4 |
+
/* Hugginface config: */
|
5 |
+
ollama: false,
|
6 |
+
huggingface: true,
|
7 |
+
url: "https://api-inference.huggingface.co/models/meta-llama/Meta-Llama-3-8B-Instruct",
|
8 |
+
chatModel: "meta-llama/Meta-Llama-3-8B-Instruct",
|
9 |
+
embeddingModel:
|
10 |
+
"https://api-inference.huggingface.co/models/mixedbread-ai/mxbai-embed-large-v1",
|
11 |
+
embeddingDimension: 1024,
|
12 |
+
|
13 |
+
/* Ollama (local) config:
|
14 |
+
*/
|
15 |
+
// ollama: true,
|
16 |
+
// url: 'http://127.0.0.1:11434',
|
17 |
+
// chatModel: 'llama3' as const,
|
18 |
+
// embeddingModel: 'mxbai-embed-large',
|
19 |
+
// embeddingDimension: 1024,
|
20 |
+
// embeddingModel: 'llama3',
|
21 |
+
// embeddingDimension: 4096,
|
22 |
+
|
23 |
+
/* Together.ai config:
|
24 |
+
ollama: false,
|
25 |
+
url: 'https://api.together.xyz',
|
26 |
+
chatModel: 'meta-llama/Llama-3-8b-chat-hf',
|
27 |
+
embeddingModel: 'togethercomputer/m2-bert-80M-8k-retrieval',
|
28 |
+
embeddingDimension: 768,
|
29 |
+
*/
|
30 |
+
|
31 |
+
/* OpenAI config:
|
32 |
+
ollama: false,
|
33 |
+
url: 'https://api.openai.com',
|
34 |
+
chatModel: 'gpt-3.5-turbo-16k',
|
35 |
+
embeddingModel: 'text-embedding-ada-002',
|
36 |
+
embeddingDimension: 1536,
|
37 |
+
*/
|
38 |
+
};
|
39 |
+
|
40 |
+
function apiUrl(path: string) {
|
41 |
+
// OPENAI_API_BASE and OLLAMA_HOST are legacy
|
42 |
+
const host =
|
43 |
+
process.env.LLM_API_URL ??
|
44 |
+
process.env.OLLAMA_HOST ??
|
45 |
+
process.env.OPENAI_API_BASE ??
|
46 |
+
LLM_CONFIG.url;
|
47 |
+
if (host.endsWith("/") && path.startsWith("/")) {
|
48 |
+
return host + path.slice(1);
|
49 |
+
} else if (!host.endsWith("/") && !path.startsWith("/")) {
|
50 |
+
return host + "/" + path;
|
51 |
+
} else {
|
52 |
+
return host + path;
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
function apiKey() {
|
57 |
+
return process.env.LLM_API_KEY ?? process.env.OPENAI_API_KEY;
|
58 |
+
}
|
59 |
+
|
60 |
+
const AuthHeaders = (): Record<string, string> =>
|
61 |
+
apiKey()
|
62 |
+
? {
|
63 |
+
Authorization: "Bearer " + apiKey(),
|
64 |
+
}
|
65 |
+
: {};
|
66 |
+
|
67 |
+
// Overload for non-streaming
|
68 |
+
export async function chatCompletion(
|
69 |
+
body: Omit<CreateChatCompletionRequest, "model"> & {
|
70 |
+
model?: CreateChatCompletionRequest["model"];
|
71 |
+
} & {
|
72 |
+
stream?: false | null | undefined;
|
73 |
+
}
|
74 |
+
): Promise<{ content: string; retries: number; ms: number }>;
|
75 |
+
// Overload for streaming
|
76 |
+
export async function chatCompletion(
|
77 |
+
body: Omit<CreateChatCompletionRequest, "model"> & {
|
78 |
+
model?: CreateChatCompletionRequest["model"];
|
79 |
+
} & {
|
80 |
+
stream?: true;
|
81 |
+
}
|
82 |
+
): Promise<{ content: ChatCompletionContent; retries: number; ms: number }>;
|
83 |
+
export async function chatCompletion(
|
84 |
+
body: Omit<CreateChatCompletionRequest, "model"> & {
|
85 |
+
model?: CreateChatCompletionRequest["model"];
|
86 |
+
}
|
87 |
+
) {
|
88 |
+
assertApiKey();
|
89 |
+
// OLLAMA_MODEL is legacy
|
90 |
+
body.model =
|
91 |
+
body.model ??
|
92 |
+
process.env.LLM_MODEL ??
|
93 |
+
process.env.OLLAMA_MODEL ??
|
94 |
+
LLM_CONFIG.chatModel;
|
95 |
+
const stopWords = body.stop
|
96 |
+
? typeof body.stop === "string"
|
97 |
+
? [body.stop]
|
98 |
+
: body.stop
|
99 |
+
: [];
|
100 |
+
if (LLM_CONFIG.ollama || LLM_CONFIG.huggingface) stopWords.push("<|eot_id|>");
|
101 |
+
|
102 |
+
const {
|
103 |
+
result: content,
|
104 |
+
retries,
|
105 |
+
ms,
|
106 |
+
} = await retryWithBackoff(async () => {
|
107 |
+
const hf = new HfInference(apiKey());
|
108 |
+
const model = hf.endpoint(apiUrl("/v1/chat/completions"));
|
109 |
+
if (body.stream) {
|
110 |
+
const completion = model.chatCompletionStream({
|
111 |
+
...body,
|
112 |
+
});
|
113 |
+
return new ChatCompletionContent(completion, stopWords);
|
114 |
+
} else {
|
115 |
+
const completion = await model.chatCompletion({
|
116 |
+
...body,
|
117 |
+
});
|
118 |
+
const content = completion.choices[0].message?.content;
|
119 |
+
if (content === undefined) {
|
120 |
+
throw new Error(
|
121 |
+
"Unexpected result from OpenAI: " + JSON.stringify(completion)
|
122 |
+
);
|
123 |
+
}
|
124 |
+
return content;
|
125 |
+
}
|
126 |
+
});
|
127 |
+
|
128 |
+
return {
|
129 |
+
content,
|
130 |
+
retries,
|
131 |
+
ms,
|
132 |
+
};
|
133 |
+
}
|
134 |
+
|
135 |
+
export async function tryPullOllama(model: string, error: string) {
|
136 |
+
if (error.includes("try pulling")) {
|
137 |
+
console.error("Embedding model not found, pulling from Ollama");
|
138 |
+
const pullResp = await fetch(apiUrl("/api/pull"), {
|
139 |
+
method: "POST",
|
140 |
+
headers: {
|
141 |
+
"Content-Type": "application/json",
|
142 |
+
},
|
143 |
+
body: JSON.stringify({ name: model }),
|
144 |
+
});
|
145 |
+
console.log("Pull response", await pullResp.text());
|
146 |
+
throw {
|
147 |
+
retry: true,
|
148 |
+
error: `Dynamically pulled model. Original error: ${error}`,
|
149 |
+
};
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
export async function fetchEmbeddingBatch(texts: string[]) {
|
154 |
+
if (LLM_CONFIG.ollama) {
|
155 |
+
return {
|
156 |
+
ollama: true as const,
|
157 |
+
embeddings: await Promise.all(
|
158 |
+
texts.map(async (t) => (await ollamaFetchEmbedding(t)).embedding)
|
159 |
+
),
|
160 |
+
};
|
161 |
+
}
|
162 |
+
assertApiKey();
|
163 |
+
|
164 |
+
if (LLM_CONFIG.huggingface) {
|
165 |
+
const result = await fetch(LLM_CONFIG.embeddingModel, {
|
166 |
+
method: "POST",
|
167 |
+
headers: {
|
168 |
+
"Content-Type": "application/json",
|
169 |
+
"X-Wait-For-Model": "true",
|
170 |
+
...AuthHeaders(),
|
171 |
+
},
|
172 |
+
body: JSON.stringify({
|
173 |
+
inputs: texts.map((text) => text.replace(/\n/g, " ")),
|
174 |
+
}),
|
175 |
+
});
|
176 |
+
const embeddings = await result.json();
|
177 |
+
return {
|
178 |
+
ollama: true as const,
|
179 |
+
embeddings: embeddings,
|
180 |
+
};
|
181 |
+
}
|
182 |
+
|
183 |
+
const {
|
184 |
+
result: json,
|
185 |
+
retries,
|
186 |
+
ms,
|
187 |
+
} = await retryWithBackoff(async () => {
|
188 |
+
const result = await fetch(apiUrl("/v1/embeddings"), {
|
189 |
+
method: "POST",
|
190 |
+
headers: {
|
191 |
+
"Content-Type": "application/json",
|
192 |
+
...AuthHeaders(),
|
193 |
+
},
|
194 |
+
|
195 |
+
body: JSON.stringify({
|
196 |
+
model: LLM_CONFIG.embeddingModel,
|
197 |
+
input: texts.map((text) => text.replace(/\n/g, " ")),
|
198 |
+
}),
|
199 |
+
});
|
200 |
+
if (!result.ok) {
|
201 |
+
throw {
|
202 |
+
retry: result.status === 429 || result.status >= 500,
|
203 |
+
error: new Error(
|
204 |
+
`Embedding failed with code ${result.status}: ${await result.text()}`
|
205 |
+
),
|
206 |
+
};
|
207 |
+
}
|
208 |
+
return (await result.json()) as CreateEmbeddingResponse;
|
209 |
+
});
|
210 |
+
if (json.data.length !== texts.length) {
|
211 |
+
console.error(json);
|
212 |
+
throw new Error("Unexpected number of embeddings");
|
213 |
+
}
|
214 |
+
const allembeddings = json.data;
|
215 |
+
allembeddings.sort((a, b) => a.index - b.index);
|
216 |
+
return {
|
217 |
+
ollama: false as const,
|
218 |
+
embeddings: allembeddings.map(({ embedding }) => embedding),
|
219 |
+
usage: json.usage?.total_tokens,
|
220 |
+
retries,
|
221 |
+
ms,
|
222 |
+
};
|
223 |
+
}
|
224 |
+
|
225 |
+
export async function fetchEmbedding(text: string) {
|
226 |
+
const { embeddings, ...stats } = await fetchEmbeddingBatch([text]);
|
227 |
+
return { embedding: embeddings[0], ...stats };
|
228 |
+
}
|
229 |
+
|
230 |
+
export async function fetchModeration(content: string) {
|
231 |
+
assertApiKey();
|
232 |
+
const { result: flagged } = await retryWithBackoff(async () => {
|
233 |
+
const result = await fetch(apiUrl("/v1/moderations"), {
|
234 |
+
method: "POST",
|
235 |
+
headers: {
|
236 |
+
"Content-Type": "application/json",
|
237 |
+
...AuthHeaders(),
|
238 |
+
},
|
239 |
+
|
240 |
+
body: JSON.stringify({
|
241 |
+
input: content,
|
242 |
+
}),
|
243 |
+
});
|
244 |
+
if (!result.ok) {
|
245 |
+
throw {
|
246 |
+
retry: result.status === 429 || result.status >= 500,
|
247 |
+
error: new Error(
|
248 |
+
`Embedding failed with code ${result.status}: ${await result.text()}`
|
249 |
+
),
|
250 |
+
};
|
251 |
+
}
|
252 |
+
return (await result.json()) as { results: { flagged: boolean }[] };
|
253 |
+
});
|
254 |
+
return flagged;
|
255 |
+
}
|
256 |
+
|
257 |
+
export function assertApiKey() {
|
258 |
+
if (!LLM_CONFIG.ollama && !apiKey()) {
|
259 |
+
throw new Error(
|
260 |
+
"\n Missing LLM_API_KEY in environment variables.\n\n" +
|
261 |
+
(LLM_CONFIG.ollama ? "just" : "npx") +
|
262 |
+
" convex env set LLM_API_KEY 'your-key'"
|
263 |
+
);
|
264 |
+
}
|
265 |
+
}
|
266 |
+
|
267 |
+
// Retry after this much time, based on the retry number.
|
268 |
+
const RETRY_BACKOFF = [1000, 10_000, 20_000]; // In ms
|
269 |
+
const RETRY_JITTER = 100; // In ms
|
270 |
+
type RetryError = { retry: boolean; error: any };
|
271 |
+
|
272 |
+
export async function retryWithBackoff<T>(
|
273 |
+
fn: () => Promise<T>
|
274 |
+
): Promise<{ retries: number; result: T; ms: number }> {
|
275 |
+
let i = 0;
|
276 |
+
for (; i <= RETRY_BACKOFF.length; i++) {
|
277 |
+
try {
|
278 |
+
const start = Date.now();
|
279 |
+
const result = await fn();
|
280 |
+
const ms = Date.now() - start;
|
281 |
+
return { result, retries: i, ms };
|
282 |
+
} catch (e) {
|
283 |
+
const retryError = e as RetryError;
|
284 |
+
if (i < RETRY_BACKOFF.length) {
|
285 |
+
if (retryError.retry) {
|
286 |
+
console.log(
|
287 |
+
`Attempt ${i + 1} failed, waiting ${
|
288 |
+
RETRY_BACKOFF[i]
|
289 |
+
}ms to retry...`,
|
290 |
+
Date.now()
|
291 |
+
);
|
292 |
+
await new Promise((resolve) =>
|
293 |
+
setTimeout(resolve, RETRY_BACKOFF[i] + RETRY_JITTER * Math.random())
|
294 |
+
);
|
295 |
+
continue;
|
296 |
+
}
|
297 |
+
}
|
298 |
+
if (retryError.error) throw retryError.error;
|
299 |
+
else throw e;
|
300 |
+
}
|
301 |
+
}
|
302 |
+
throw new Error("Unreachable");
|
303 |
+
}
|
304 |
+
|
305 |
+
// Lifted from openai's package
|
306 |
+
export interface LLMMessage {
|
307 |
+
/**
|
308 |
+
* The contents of the message. `content` is required for all messages, and may be
|
309 |
+
* null for assistant messages with function calls.
|
310 |
+
*/
|
311 |
+
content: string | null;
|
312 |
+
|
313 |
+
/**
|
314 |
+
* The role of the messages author. One of `system`, `user`, `assistant`, or
|
315 |
+
* `function`.
|
316 |
+
*/
|
317 |
+
role: "system" | "user" | "assistant" | "function";
|
318 |
+
|
319 |
+
/**
|
320 |
+
* The name of the author of this message. `name` is required if role is
|
321 |
+
* `function`, and it should be the name of the function whose response is in the
|
322 |
+
* `content`. May contain a-z, A-Z, 0-9, and underscores, with a maximum length of
|
323 |
+
* 64 characters.
|
324 |
+
*/
|
325 |
+
name?: string;
|
326 |
+
|
327 |
+
/**
|
328 |
+
* The name and arguments of a function that should be called, as generated by the model.
|
329 |
+
*/
|
330 |
+
function_call?: {
|
331 |
+
// The name of the function to call.
|
332 |
+
name: string;
|
333 |
+
/**
|
334 |
+
* The arguments to call the function with, as generated by the model in
|
335 |
+
* JSON format. Note that the model does not always generate valid JSON,
|
336 |
+
* and may hallucinate parameters not defined by your function schema.
|
337 |
+
* Validate the arguments in your code before calling your function.
|
338 |
+
*/
|
339 |
+
arguments: string;
|
340 |
+
};
|
341 |
+
}
|
342 |
+
|
343 |
+
// Non-streaming chat completion response
|
344 |
+
interface CreateChatCompletionResponse {
|
345 |
+
id: string;
|
346 |
+
object: string;
|
347 |
+
created: number;
|
348 |
+
model: string;
|
349 |
+
choices: {
|
350 |
+
index?: number;
|
351 |
+
message?: {
|
352 |
+
role: "system" | "user" | "assistant";
|
353 |
+
content: string;
|
354 |
+
};
|
355 |
+
finish_reason?: string;
|
356 |
+
}[];
|
357 |
+
usage?: {
|
358 |
+
completion_tokens: number;
|
359 |
+
|
360 |
+
prompt_tokens: number;
|
361 |
+
|
362 |
+
total_tokens: number;
|
363 |
+
};
|
364 |
+
}
|
365 |
+
|
366 |
+
interface CreateEmbeddingResponse {
|
367 |
+
data: {
|
368 |
+
index: number;
|
369 |
+
object: string;
|
370 |
+
embedding: number[];
|
371 |
+
}[];
|
372 |
+
model: string;
|
373 |
+
object: string;
|
374 |
+
usage: {
|
375 |
+
prompt_tokens: number;
|
376 |
+
total_tokens: number;
|
377 |
+
};
|
378 |
+
}
|
379 |
+
|
380 |
+
export interface CreateChatCompletionRequest {
|
381 |
+
/**
|
382 |
+
* ID of the model to use.
|
383 |
+
* @type {string}
|
384 |
+
* @memberof CreateChatCompletionRequest
|
385 |
+
*/
|
386 |
+
model: string;
|
387 |
+
// | 'gpt-4'
|
388 |
+
// | 'gpt-4-0613'
|
389 |
+
// | 'gpt-4-32k'
|
390 |
+
// | 'gpt-4-32k-0613'
|
391 |
+
// | 'gpt-3.5-turbo'
|
392 |
+
// | 'gpt-3.5-turbo-0613'
|
393 |
+
// | 'gpt-3.5-turbo-16k' // <- our default
|
394 |
+
// | 'gpt-3.5-turbo-16k-0613';
|
395 |
+
/**
|
396 |
+
* The messages to generate chat completions for, in the chat format:
|
397 |
+
* https://platform.openai.com/docs/guides/chat/introduction
|
398 |
+
* @type {Array<ChatCompletionRequestMessage>}
|
399 |
+
* @memberof CreateChatCompletionRequest
|
400 |
+
*/
|
401 |
+
messages: LLMMessage[];
|
402 |
+
/**
|
403 |
+
* What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend altering this or `top_p` but not both.
|
404 |
+
* @type {number}
|
405 |
+
* @memberof CreateChatCompletionRequest
|
406 |
+
*/
|
407 |
+
temperature?: number | null;
|
408 |
+
/**
|
409 |
+
* An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or `temperature` but not both.
|
410 |
+
* @type {number}
|
411 |
+
* @memberof CreateChatCompletionRequest
|
412 |
+
*/
|
413 |
+
top_p?: number | null;
|
414 |
+
/**
|
415 |
+
* How many chat completion choices to generate for each input message.
|
416 |
+
* @type {number}
|
417 |
+
* @memberof CreateChatCompletionRequest
|
418 |
+
*/
|
419 |
+
n?: number | null;
|
420 |
+
/**
|
421 |
+
* If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message.
|
422 |
+
* @type {boolean}
|
423 |
+
* @memberof CreateChatCompletionRequest
|
424 |
+
*/
|
425 |
+
stream?: boolean | null;
|
426 |
+
/**
|
427 |
+
*
|
428 |
+
* @type {CreateChatCompletionRequestStop}
|
429 |
+
* @memberof CreateChatCompletionRequest
|
430 |
+
*/
|
431 |
+
stop?: Array<string> | string;
|
432 |
+
/**
|
433 |
+
* The maximum number of tokens allowed for the generated answer. By default,
|
434 |
+
* the number of tokens the model can return will be (4096 - prompt tokens).
|
435 |
+
* @type {number}
|
436 |
+
* @memberof CreateChatCompletionRequest
|
437 |
+
*/
|
438 |
+
max_tokens?: number;
|
439 |
+
/**
|
440 |
+
* Number between -2.0 and 2.0. Positive values penalize new tokens based on
|
441 |
+
* whether they appear in the text so far, increasing the model\'s likelihood
|
442 |
+
* to talk about new topics. See more information about frequency and
|
443 |
+
* presence penalties:
|
444 |
+
* https://platform.openai.com/docs/api-reference/parameter-details
|
445 |
+
* @type {number}
|
446 |
+
* @memberof CreateChatCompletionRequest
|
447 |
+
*/
|
448 |
+
presence_penalty?: number | null;
|
449 |
+
/**
|
450 |
+
* Number between -2.0 and 2.0. Positive values penalize new tokens based on
|
451 |
+
* their existing frequency in the text so far, decreasing the model\'s
|
452 |
+
* likelihood to repeat the same line verbatim. See more information about
|
453 |
+
* presence penalties:
|
454 |
+
* https://platform.openai.com/docs/api-reference/parameter-details
|
455 |
+
* @type {number}
|
456 |
+
* @memberof CreateChatCompletionRequest
|
457 |
+
*/
|
458 |
+
frequency_penalty?: number | null;
|
459 |
+
/**
|
460 |
+
* Modify the likelihood of specified tokens appearing in the completion.
|
461 |
+
* Accepts a json object that maps tokens (specified by their token ID in the
|
462 |
+
* tokenizer) to an associated bias value from -100 to 100. Mathematically,
|
463 |
+
* the bias is added to the logits generated by the model prior to sampling.
|
464 |
+
* The exact effect will vary per model, but values between -1 and 1 should
|
465 |
+
* decrease or increase likelihood of selection; values like -100 or 100
|
466 |
+
* should result in a ban or exclusive selection of the relevant token.
|
467 |
+
* @type {object}
|
468 |
+
* @memberof CreateChatCompletionRequest
|
469 |
+
*/
|
470 |
+
logit_bias?: object | null;
|
471 |
+
/**
|
472 |
+
* A unique identifier representing your end-user, which can help OpenAI to
|
473 |
+
* monitor and detect abuse. Learn more:
|
474 |
+
* https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids
|
475 |
+
* @type {string}
|
476 |
+
* @memberof CreateChatCompletionRequest
|
477 |
+
*/
|
478 |
+
user?: string;
|
479 |
+
tools?: {
|
480 |
+
// The type of the tool. Currently, only function is supported.
|
481 |
+
type: "function";
|
482 |
+
function: {
|
483 |
+
/**
|
484 |
+
* The name of the function to be called. Must be a-z, A-Z, 0-9, or
|
485 |
+
* contain underscores and dashes, with a maximum length of 64.
|
486 |
+
*/
|
487 |
+
name: string;
|
488 |
+
/**
|
489 |
+
* A description of what the function does, used by the model to choose
|
490 |
+
* when and how to call the function.
|
491 |
+
*/
|
492 |
+
description?: string;
|
493 |
+
/**
|
494 |
+
* The parameters the functions accepts, described as a JSON Schema
|
495 |
+
* object. See the guide[1] for examples, and the JSON Schema reference[2]
|
496 |
+
* for documentation about the format.
|
497 |
+
* [1]: https://platform.openai.com/docs/guides/gpt/function-calling
|
498 |
+
* [2]: https://json-schema.org/understanding-json-schema/
|
499 |
+
* To describe a function that accepts no parameters, provide the value
|
500 |
+
* {"type": "object", "properties": {}}.
|
501 |
+
*/
|
502 |
+
parameters: object;
|
503 |
+
};
|
504 |
+
}[];
|
505 |
+
/**
|
506 |
+
* Controls which (if any) function is called by the model. `none` means the
|
507 |
+
* model will not call a function and instead generates a message.
|
508 |
+
* `auto` means the model can pick between generating a message or calling a
|
509 |
+
* function. Specifying a particular function via
|
510 |
+
* {"type: "function", "function": {"name": "my_function"}} forces the model
|
511 |
+
* to call that function.
|
512 |
+
*
|
513 |
+
* `none` is the default when no functions are present.
|
514 |
+
* `auto` is the default if functions are present.
|
515 |
+
*/
|
516 |
+
tool_choice?:
|
517 |
+
| "none" // none means the model will not call a function and instead generates a message.
|
518 |
+
| "auto" // auto means the model can pick between generating a message or calling a function.
|
519 |
+
// Specifies a tool the model should use. Use to force the model to call
|
520 |
+
// a specific function.
|
521 |
+
| {
|
522 |
+
// The type of the tool. Currently, only function is supported.
|
523 |
+
type: "function";
|
524 |
+
function: { name: string };
|
525 |
+
};
|
526 |
+
// Replaced by "tools"
|
527 |
+
// functions?: {
|
528 |
+
// /**
|
529 |
+
// * The name of the function to be called. Must be a-z, A-Z, 0-9, or
|
530 |
+
// * contain underscores and dashes, with a maximum length of 64.
|
531 |
+
// */
|
532 |
+
// name: string;
|
533 |
+
// /**
|
534 |
+
// * A description of what the function does, used by the model to choose
|
535 |
+
// * when and how to call the function.
|
536 |
+
// */
|
537 |
+
// description?: string;
|
538 |
+
// /**
|
539 |
+
// * The parameters the functions accepts, described as a JSON Schema
|
540 |
+
// * object. See the guide[1] for examples, and the JSON Schema reference[2]
|
541 |
+
// * for documentation about the format.
|
542 |
+
// * [1]: https://platform.openai.com/docs/guides/gpt/function-calling
|
543 |
+
// * [2]: https://json-schema.org/understanding-json-schema/
|
544 |
+
// * To describe a function that accepts no parameters, provide the value
|
545 |
+
// * {"type": "object", "properties": {}}.
|
546 |
+
// */
|
547 |
+
// parameters: object;
|
548 |
+
// }[];
|
549 |
+
// /**
|
550 |
+
// * Controls how the model responds to function calls. "none" means the model
|
551 |
+
// * does not call a function, and responds to the end-user. "auto" means the
|
552 |
+
// * model can pick between an end-user or calling a function. Specifying a
|
553 |
+
// * particular function via {"name":\ "my_function"} forces the model to call
|
554 |
+
// * that function.
|
555 |
+
// * - "none" is the default when no functions are present.
|
556 |
+
// * - "auto" is the default if functions are present.
|
557 |
+
// */
|
558 |
+
// function_call?: 'none' | 'auto' | { name: string };
|
559 |
+
/**
|
560 |
+
* An object specifying the format that the model must output.
|
561 |
+
*
|
562 |
+
* Setting to { "type": "json_object" } enables JSON mode, which guarantees
|
563 |
+
* the message the model generates is valid JSON.
|
564 |
+
* *Important*: when using JSON mode, you must also instruct the model to
|
565 |
+
* produce JSON yourself via a system or user message. Without this, the model
|
566 |
+
* may generate an unending stream of whitespace until the generation reaches
|
567 |
+
* the token limit, resulting in a long-running and seemingly "stuck" request.
|
568 |
+
* Also note that the message content may be partially cut off if
|
569 |
+
* finish_reason="length", which indicates the generation exceeded max_tokens
|
570 |
+
* or the conversation exceeded the max context length.
|
571 |
+
*/
|
572 |
+
response_format?: { type: "text" | "json_object" };
|
573 |
+
}
|
574 |
+
|
575 |
+
// Checks whether a suffix of s1 is a prefix of s2. For example,
|
576 |
+
// ('Hello', 'Kira:') -> false
|
577 |
+
// ('Hello Kira', 'Kira:') -> true
|
578 |
+
const suffixOverlapsPrefix = (s1: string, s2: string) => {
|
579 |
+
for (let i = 1; i <= Math.min(s1.length, s2.length); i++) {
|
580 |
+
const suffix = s1.substring(s1.length - i);
|
581 |
+
const prefix = s2.substring(0, i);
|
582 |
+
if (suffix === prefix) {
|
583 |
+
return true;
|
584 |
+
}
|
585 |
+
}
|
586 |
+
return false;
|
587 |
+
};
|
588 |
+
|
589 |
+
export class ChatCompletionContent {
|
590 |
+
private readonly completion: AsyncIterable<ChatCompletionChunk>;
|
591 |
+
private readonly stopWords: string[];
|
592 |
+
|
593 |
+
constructor(
|
594 |
+
completion: AsyncIterable<ChatCompletionChunk>,
|
595 |
+
stopWords: string[]
|
596 |
+
) {
|
597 |
+
this.completion = completion;
|
598 |
+
this.stopWords = stopWords;
|
599 |
+
}
|
600 |
+
|
601 |
+
async *readInner() {
|
602 |
+
for await (const chunk of this.completion) {
|
603 |
+
yield chunk.choices[0].delta.content;
|
604 |
+
}
|
605 |
+
}
|
606 |
+
|
607 |
+
// stop words in OpenAI api don't always work.
|
608 |
+
// So we have to truncate on our side.
|
609 |
+
async *read() {
|
610 |
+
let lastFragment = "";
|
611 |
+
for await (const data of this.readInner()) {
|
612 |
+
lastFragment += data;
|
613 |
+
let hasOverlap = false;
|
614 |
+
for (const stopWord of this.stopWords) {
|
615 |
+
const idx = lastFragment.indexOf(stopWord);
|
616 |
+
if (idx >= 0) {
|
617 |
+
yield lastFragment.substring(0, idx);
|
618 |
+
return;
|
619 |
+
}
|
620 |
+
if (suffixOverlapsPrefix(lastFragment, stopWord)) {
|
621 |
+
hasOverlap = true;
|
622 |
+
}
|
623 |
+
}
|
624 |
+
if (hasOverlap) continue;
|
625 |
+
yield lastFragment;
|
626 |
+
lastFragment = "";
|
627 |
+
}
|
628 |
+
yield lastFragment;
|
629 |
+
}
|
630 |
+
|
631 |
+
async readAll() {
|
632 |
+
let allContent = "";
|
633 |
+
for await (const chunk of this.read()) {
|
634 |
+
allContent += chunk;
|
635 |
+
}
|
636 |
+
return allContent;
|
637 |
+
}
|
638 |
+
}
|
639 |
+
|
640 |
+
export async function ollamaFetchEmbedding(text: string) {
|
641 |
+
const { result } = await retryWithBackoff(async () => {
|
642 |
+
const resp = await fetch(apiUrl("/api/embeddings"), {
|
643 |
+
method: "POST",
|
644 |
+
headers: {
|
645 |
+
"Content-Type": "application/json",
|
646 |
+
},
|
647 |
+
body: JSON.stringify({ model: LLM_CONFIG.embeddingModel, prompt: text }),
|
648 |
+
});
|
649 |
+
if (resp.status === 404) {
|
650 |
+
const error = await resp.text();
|
651 |
+
await tryPullOllama(LLM_CONFIG.embeddingModel, error);
|
652 |
+
throw new Error(`Failed to fetch embeddings: ${resp.status}`);
|
653 |
+
}
|
654 |
+
return (await resp.json()).embedding as number[];
|
655 |
+
});
|
656 |
+
return { embedding: result };
|
657 |
+
}
|
patches/patches/music.ts
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { v } from 'convex/values';
|
2 |
+
import { query, internalMutation } from './_generated/server';
|
3 |
+
import Replicate, { WebhookEventType } from 'replicate';
|
4 |
+
import { httpAction, internalAction } from './_generated/server';
|
5 |
+
import { internal, api } from './_generated/api';
|
6 |
+
|
7 |
+
function client(): Replicate {
|
8 |
+
const replicate = new Replicate({
|
9 |
+
auth: process.env.REPLICATE_API_TOKEN || '',
|
10 |
+
});
|
11 |
+
return replicate;
|
12 |
+
}
|
13 |
+
|
14 |
+
function replicateAvailable(): boolean {
|
15 |
+
return !!process.env.REPLICATE_API_TOKEN;
|
16 |
+
}
|
17 |
+
|
18 |
+
export const insertMusic = internalMutation({
|
19 |
+
args: { storageId: v.string(), type: v.union(v.literal('background'), v.literal('player')) },
|
20 |
+
handler: async (ctx, args) => {
|
21 |
+
await ctx.db.insert('music', {
|
22 |
+
storageId: args.storageId,
|
23 |
+
type: args.type,
|
24 |
+
});
|
25 |
+
},
|
26 |
+
});
|
27 |
+
|
28 |
+
export const getBackgroundMusic = query({
|
29 |
+
handler: async (ctx) => {
|
30 |
+
const music = await ctx.db
|
31 |
+
.query('music')
|
32 |
+
.filter((entry) => entry.eq(entry.field('type'), 'background'))
|
33 |
+
.order('desc')
|
34 |
+
.first();
|
35 |
+
if (!music) {
|
36 |
+
return '/assets/background.mp3';
|
37 |
+
}
|
38 |
+
const url = await ctx.storage.getUrl(music.storageId);
|
39 |
+
if (!url) {
|
40 |
+
throw new Error(`Invalid storage ID: ${music.storageId}`);
|
41 |
+
}
|
42 |
+
return url;
|
43 |
+
},
|
44 |
+
});
|
45 |
+
|
46 |
+
export const enqueueBackgroundMusicGeneration = internalAction({
|
47 |
+
handler: async (ctx): Promise<void> => {
|
48 |
+
if (!replicateAvailable()) {
|
49 |
+
return;
|
50 |
+
}
|
51 |
+
const worldStatus = await ctx.runQuery(api.world.defaultWorldStatus);
|
52 |
+
if (!worldStatus) {
|
53 |
+
console.log('No active default world, returning.');
|
54 |
+
return;
|
55 |
+
}
|
56 |
+
// TODO: MusicGen-Large on Replicate only allows 30 seconds. Use MusicGen-Small for longer?
|
57 |
+
await generateMusic('16-bit RPG adventure game with wholesome vibe', 30);
|
58 |
+
},
|
59 |
+
});
|
60 |
+
|
61 |
+
export const handleReplicateWebhook = httpAction(async (ctx, request) => {
|
62 |
+
const req = await request.json();
|
63 |
+
if (req.id) {
|
64 |
+
const prediction = await client().predictions.get(req.id);
|
65 |
+
const response = await fetch(prediction.output);
|
66 |
+
const music = await response.blob();
|
67 |
+
const storageId = await ctx.storage.store(music);
|
68 |
+
await ctx.runMutation(internal.music.insertMusic, { type: 'background', storageId });
|
69 |
+
}
|
70 |
+
return new Response();
|
71 |
+
});
|
72 |
+
|
73 |
+
enum MusicGenNormStrategy {
|
74 |
+
Clip = 'clip',
|
75 |
+
Loudness = 'loudness',
|
76 |
+
Peak = 'peak',
|
77 |
+
Rms = 'rms',
|
78 |
+
}
|
79 |
+
|
80 |
+
enum MusicGenFormat {
|
81 |
+
wav = 'wav',
|
82 |
+
mp3 = 'mp3',
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
*
|
87 |
+
* @param prompt A description of the music you want to generate.
|
88 |
+
* @param duration Duration of the generated audio in seconds.
|
89 |
+
* @param webhook webhook URL for Replicate to call when @param webhook_events_filter is triggered
|
90 |
+
* @param webhook_events_filter Array of event names to filter the webhook. See https://replicate.com/docs/reference/http#predictions.create--webhook_events_filter
|
91 |
+
* @param normalization_strategy Strategy for normalizing audio.
|
92 |
+
* @param top_k Reduces sampling to the k most likely tokens.
|
93 |
+
* @param top_p Reduces sampling to tokens with cumulative probability of p. When set to `0` (default), top_k sampling is used.
|
94 |
+
* @param temperature Controls the 'conservativeness' of the sampling process. Higher temperature means more diversity.
|
95 |
+
* @param classifer_free_gudance Increases the influence of inputs on the output. Higher values produce lower-varience outputs that adhere more closely to inputs.
|
96 |
+
* @param output_format Output format for generated audio. See @
|
97 |
+
* @param seed Seed for random number generator. If None or -1, a random seed will be used.
|
98 |
+
* @returns object containing metadata of the prediction with ID to fetch once result is completed
|
99 |
+
*/
|
100 |
+
export async function generateMusic(
|
101 |
+
prompt: string,
|
102 |
+
duration: number,
|
103 |
+
webhook: string = process.env.CONVEX_SITE_URL + '/replicate_webhook' || '',
|
104 |
+
webhook_events_filter: [WebhookEventType] = ['completed'],
|
105 |
+
normalization_strategy: MusicGenNormStrategy = MusicGenNormStrategy.Peak,
|
106 |
+
output_format: MusicGenFormat = MusicGenFormat.mp3,
|
107 |
+
top_k = 250,
|
108 |
+
top_p = 0,
|
109 |
+
temperature = 1,
|
110 |
+
classifer_free_gudance = 3,
|
111 |
+
seed = -1,
|
112 |
+
model_version = 'large',
|
113 |
+
) {
|
114 |
+
if (!replicateAvailable()) {
|
115 |
+
throw new Error('Replicate API token not set');
|
116 |
+
}
|
117 |
+
return await client().predictions.create({
|
118 |
+
// https://replicate.com/facebookresearch/musicgen/versions/7a76a8258b23fae65c5a22debb8841d1d7e816b75c2f24218cd2bd8573787906
|
119 |
+
version: '7a76a8258b23fae65c5a22debb8841d1d7e816b75c2f24218cd2bd8573787906',
|
120 |
+
input: {
|
121 |
+
model_version,
|
122 |
+
prompt,
|
123 |
+
duration,
|
124 |
+
normalization_strategy,
|
125 |
+
top_k,
|
126 |
+
top_p,
|
127 |
+
temperature,
|
128 |
+
classifer_free_gudance,
|
129 |
+
output_format,
|
130 |
+
seed,
|
131 |
+
},
|
132 |
+
webhook,
|
133 |
+
webhook_events_filter,
|
134 |
+
});
|
135 |
+
}
|
patches/patches/run.sh
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
run_convex_command() {
|
3 |
+
npx convex "$@" --admin-key 0135d8598650f8f5cb0f30c34ec2e2bb62793bc28717c8eb6fb577996d50be5f4281b59181095065c5d0f86a2c31ddbe9b597ec62b47ded69782cd --url "http://0.0.0.0:3210"
|
4 |
+
}
|
5 |
+
|
6 |
+
./convex-local-backend &
|
7 |
+
run_convex_command env set LLM_API_KEY $HF_TOKEN &
|
8 |
+
run_convex_command dev --run init --until-success &
|
9 |
+
run_convex_command deploy &
|
10 |
+
|
11 |
+
# run_convex_command dev --run init --until-success &
|
12 |
+
# run_convex_command dev --tail-logs &
|
13 |
+
# you need to set VITE_CONVEX_URL to the Vite Server proxied version
|
14 |
+
if [ -z "$SPACE_HOST" ]; then
|
15 |
+
export VITE_CONVEX_URL=http://localhost:5173/backend.convex.cloud
|
16 |
+
else
|
17 |
+
export VITE_CONVEX_URL=https://$SPACE_HOST/backend.convex.cloud
|
18 |
+
fi
|
19 |
+
|
20 |
+
export VITE_OAUTH_CLIENT_ID=$OAUTH_CLIENT_ID
|
21 |
+
# Unsure if the following are necessary
|
22 |
+
# export OAUTH_CLIENT_SECRET=$OAUTH_CLIENT_SECRET
|
23 |
+
# export OAUTH_SCOPES=$OAUTH_SCOPES
|
24 |
+
# export OPENID_PROVIDER_URL=$OPENID_PROVIDER_URL
|
25 |
+
|
26 |
+
npm run dev:frontend -- --host 0.0.0.0 &
|
27 |
+
run_convex_command dev
|
patches/patches/vite.config.ts
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { defineConfig } from 'vite';
|
2 |
+
import react from '@vitejs/plugin-react';
|
3 |
+
|
4 |
+
// https://vitejs.dev/config/
|
5 |
+
export default defineConfig({
|
6 |
+
base: '/',
|
7 |
+
plugins: [react()],
|
8 |
+
server: {
|
9 |
+
proxy: {
|
10 |
+
'/backend.convex.cloud': {
|
11 |
+
target: 'ws://0.0.0.0:3210',
|
12 |
+
changeOrigin: true,
|
13 |
+
ws: true,
|
14 |
+
rewrite: (path) => path.replace(/^\/backend\.convex\.cloud/, '/'),
|
15 |
+
},
|
16 |
+
},
|
17 |
+
},
|
18 |
+
});
|
patches/patches/world.ts
ADDED
@@ -0,0 +1,273 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { ConvexError, v } from 'convex/values';
|
2 |
+
import { internalMutation, mutation, query } from './_generated/server';
|
3 |
+
import { characters } from '../data/characters';
|
4 |
+
import { Descriptions } from '../data/characters';
|
5 |
+
import { insertInput } from './aiTown/insertInput';
|
6 |
+
import {
|
7 |
+
DEFAULT_NAME,
|
8 |
+
ENGINE_ACTION_DURATION,
|
9 |
+
IDLE_WORLD_TIMEOUT,
|
10 |
+
WORLD_HEARTBEAT_INTERVAL,
|
11 |
+
} from './constants';
|
12 |
+
import { playerId } from './aiTown/ids';
|
13 |
+
import { kickEngine, startEngine, stopEngine } from './aiTown/main';
|
14 |
+
import { engineInsertInput } from './engine/abstractGame';
|
15 |
+
|
16 |
+
export const defaultWorldStatus = query({
|
17 |
+
handler: async (ctx) => {
|
18 |
+
const worldStatus = await ctx.db
|
19 |
+
.query('worldStatus')
|
20 |
+
.filter((q) => q.eq(q.field('isDefault'), true))
|
21 |
+
.first();
|
22 |
+
return worldStatus;
|
23 |
+
},
|
24 |
+
});
|
25 |
+
|
26 |
+
export const heartbeatWorld = mutation({
|
27 |
+
args: {
|
28 |
+
worldId: v.id('worlds'),
|
29 |
+
},
|
30 |
+
handler: async (ctx, args) => {
|
31 |
+
const worldStatus = await ctx.db
|
32 |
+
.query('worldStatus')
|
33 |
+
.withIndex('worldId', (q) => q.eq('worldId', args.worldId))
|
34 |
+
.first();
|
35 |
+
if (!worldStatus) {
|
36 |
+
throw new Error(`Invalid world ID: ${args.worldId}`);
|
37 |
+
}
|
38 |
+
const now = Date.now();
|
39 |
+
|
40 |
+
// Skip the update (and then potentially make the transaction readonly)
|
41 |
+
// if it's been viewed sufficiently recently..
|
42 |
+
if (!worldStatus.lastViewed || worldStatus.lastViewed < now - WORLD_HEARTBEAT_INTERVAL / 2) {
|
43 |
+
await ctx.db.patch(worldStatus._id, {
|
44 |
+
lastViewed: Math.max(worldStatus.lastViewed ?? now, now),
|
45 |
+
});
|
46 |
+
}
|
47 |
+
|
48 |
+
// Restart inactive worlds, but leave worlds explicitly stopped by the developer alone.
|
49 |
+
if (worldStatus.status === 'stoppedByDeveloper') {
|
50 |
+
console.debug(`World ${worldStatus._id} is stopped by developer, not restarting.`);
|
51 |
+
}
|
52 |
+
if (worldStatus.status === 'inactive') {
|
53 |
+
console.log(`Restarting inactive world ${worldStatus._id}...`);
|
54 |
+
await ctx.db.patch(worldStatus._id, { status: 'running' });
|
55 |
+
await startEngine(ctx, worldStatus.worldId);
|
56 |
+
}
|
57 |
+
},
|
58 |
+
});
|
59 |
+
|
60 |
+
export const stopInactiveWorlds = internalMutation({
|
61 |
+
handler: async (ctx) => {
|
62 |
+
const cutoff = Date.now() - IDLE_WORLD_TIMEOUT;
|
63 |
+
const worlds = await ctx.db.query('worldStatus').collect();
|
64 |
+
for (const worldStatus of worlds) {
|
65 |
+
if (cutoff < worldStatus.lastViewed || worldStatus.status !== 'running') {
|
66 |
+
continue;
|
67 |
+
}
|
68 |
+
console.log(`Stopping inactive world ${worldStatus._id}`);
|
69 |
+
await ctx.db.patch(worldStatus._id, { status: 'inactive' });
|
70 |
+
await stopEngine(ctx, worldStatus.worldId);
|
71 |
+
}
|
72 |
+
},
|
73 |
+
});
|
74 |
+
|
75 |
+
export const restartDeadWorlds = internalMutation({
|
76 |
+
handler: async (ctx) => {
|
77 |
+
const now = Date.now();
|
78 |
+
|
79 |
+
// Restart an engine if it hasn't run for 2x its action duration.
|
80 |
+
const engineTimeout = now - ENGINE_ACTION_DURATION * 2;
|
81 |
+
const worlds = await ctx.db.query('worldStatus').collect();
|
82 |
+
for (const worldStatus of worlds) {
|
83 |
+
if (worldStatus.status !== 'running') {
|
84 |
+
continue;
|
85 |
+
}
|
86 |
+
const engine = await ctx.db.get(worldStatus.engineId);
|
87 |
+
if (!engine) {
|
88 |
+
throw new Error(`Invalid engine ID: ${worldStatus.engineId}`);
|
89 |
+
}
|
90 |
+
if (engine.currentTime && engine.currentTime < engineTimeout) {
|
91 |
+
console.warn(`Restarting dead engine ${engine._id}...`);
|
92 |
+
await kickEngine(ctx, worldStatus.worldId);
|
93 |
+
}
|
94 |
+
}
|
95 |
+
},
|
96 |
+
});
|
97 |
+
|
98 |
+
export const userStatus = query({
|
99 |
+
args: {
|
100 |
+
worldId: v.id('worlds'),
|
101 |
+
oauthToken: v.optional(v.string()),
|
102 |
+
|
103 |
+
},
|
104 |
+
handler: async (ctx, args) => {
|
105 |
+
const { worldId, oauthToken } = args;
|
106 |
+
|
107 |
+
if (!oauthToken) {
|
108 |
+
return null;
|
109 |
+
}
|
110 |
+
console.log("oauthToken", oauthToken)
|
111 |
+
return oauthToken;
|
112 |
+
},
|
113 |
+
});
|
114 |
+
|
115 |
+
export const joinWorld = mutation({
|
116 |
+
args: {
|
117 |
+
worldId: v.id('worlds'),
|
118 |
+
oauthToken: v.optional(v.string()),
|
119 |
+
|
120 |
+
},
|
121 |
+
handler: async (ctx, args) => {
|
122 |
+
const { worldId, oauthToken } = args;
|
123 |
+
|
124 |
+
if (!oauthToken) {
|
125 |
+
throw new ConvexError(`Not logged in`);
|
126 |
+
}
|
127 |
+
// if (!identity) {
|
128 |
+
// throw new ConvexError(`Not logged in`);
|
129 |
+
// }
|
130 |
+
// const name =
|
131 |
+
// identity.givenName || identity.nickname || (identity.email && identity.email.split('@')[0]);
|
132 |
+
const name = oauthToken;
|
133 |
+
|
134 |
+
// if (!name) {
|
135 |
+
// throw new ConvexError(`Missing name on ${JSON.stringify(identity)}`);
|
136 |
+
// }
|
137 |
+
const world = await ctx.db.get(args.worldId);
|
138 |
+
if (!world) {
|
139 |
+
throw new ConvexError(`Invalid world ID: ${args.worldId}`);
|
140 |
+
}
|
141 |
+
// Select a random character description
|
142 |
+
const randomCharacter = Descriptions[Math.floor(Math.random() * Descriptions.length)];
|
143 |
+
|
144 |
+
return await insertInput(ctx, world._id, 'join', {
|
145 |
+
name: oauthToken,
|
146 |
+
character: randomCharacter.character,
|
147 |
+
description: "This is you !",
|
148 |
+
tokenIdentifier: oauthToken,
|
149 |
+
});
|
150 |
+
},
|
151 |
+
});
|
152 |
+
|
153 |
+
|
154 |
+
export const leaveWorld = mutation({
|
155 |
+
args: {
|
156 |
+
worldId: v.id('worlds'),
|
157 |
+
oauthToken: v.optional(v.string()),
|
158 |
+
},
|
159 |
+
handler: async (ctx, args) => {
|
160 |
+
const { worldId, oauthToken } = args;
|
161 |
+
|
162 |
+
|
163 |
+
console.log('OAuth Name:', oauthToken);
|
164 |
+
if (!oauthToken) {
|
165 |
+
throw new ConvexError(`Not logged in`);
|
166 |
+
}
|
167 |
+
|
168 |
+
const world = await ctx.db.get(args.worldId);
|
169 |
+
if (!world) {
|
170 |
+
throw new Error(`Invalid world ID: ${args.worldId}`);
|
171 |
+
}
|
172 |
+
// const existingPlayer = world.players.find((p) => p.human === tokenIdentifier);
|
173 |
+
const existingPlayer = world.players.find((p) => p.human === oauthToken);
|
174 |
+
if (!existingPlayer) {
|
175 |
+
return;
|
176 |
+
}
|
177 |
+
await insertInput(ctx, world._id, 'leave', {
|
178 |
+
playerId: existingPlayer.id,
|
179 |
+
});
|
180 |
+
},
|
181 |
+
});
|
182 |
+
|
183 |
+
export const sendWorldInput = mutation({
|
184 |
+
args: {
|
185 |
+
engineId: v.id('engines'),
|
186 |
+
name: v.string(),
|
187 |
+
args: v.any(),
|
188 |
+
},
|
189 |
+
handler: async (ctx, args) => {
|
190 |
+
// const identity = await ctx.auth.getUserIdentity();
|
191 |
+
// if (!identity) {
|
192 |
+
// throw new Error(`Not logged in`);
|
193 |
+
// }
|
194 |
+
return await engineInsertInput(ctx, args.engineId, args.name as any, args.args);
|
195 |
+
},
|
196 |
+
});
|
197 |
+
|
198 |
+
export const worldState = query({
|
199 |
+
args: {
|
200 |
+
worldId: v.id('worlds'),
|
201 |
+
},
|
202 |
+
handler: async (ctx, args) => {
|
203 |
+
const world = await ctx.db.get(args.worldId);
|
204 |
+
if (!world) {
|
205 |
+
throw new Error(`Invalid world ID: ${args.worldId}`);
|
206 |
+
}
|
207 |
+
const worldStatus = await ctx.db
|
208 |
+
.query('worldStatus')
|
209 |
+
.withIndex('worldId', (q) => q.eq('worldId', world._id))
|
210 |
+
.unique();
|
211 |
+
if (!worldStatus) {
|
212 |
+
throw new Error(`Invalid world status ID: ${world._id}`);
|
213 |
+
}
|
214 |
+
const engine = await ctx.db.get(worldStatus.engineId);
|
215 |
+
if (!engine) {
|
216 |
+
throw new Error(`Invalid engine ID: ${worldStatus.engineId}`);
|
217 |
+
}
|
218 |
+
return { world, engine };
|
219 |
+
},
|
220 |
+
});
|
221 |
+
|
222 |
+
export const gameDescriptions = query({
|
223 |
+
args: {
|
224 |
+
worldId: v.id('worlds'),
|
225 |
+
},
|
226 |
+
handler: async (ctx, args) => {
|
227 |
+
const playerDescriptions = await ctx.db
|
228 |
+
.query('playerDescriptions')
|
229 |
+
.withIndex('worldId', (q) => q.eq('worldId', args.worldId))
|
230 |
+
.collect();
|
231 |
+
const agentDescriptions = await ctx.db
|
232 |
+
.query('agentDescriptions')
|
233 |
+
.withIndex('worldId', (q) => q.eq('worldId', args.worldId))
|
234 |
+
.collect();
|
235 |
+
const worldMap = await ctx.db
|
236 |
+
.query('maps')
|
237 |
+
.withIndex('worldId', (q) => q.eq('worldId', args.worldId))
|
238 |
+
.first();
|
239 |
+
if (!worldMap) {
|
240 |
+
throw new Error(`No map for world: ${args.worldId}`);
|
241 |
+
}
|
242 |
+
return { worldMap, playerDescriptions, agentDescriptions };
|
243 |
+
},
|
244 |
+
});
|
245 |
+
|
246 |
+
export const previousConversation = query({
|
247 |
+
args: {
|
248 |
+
worldId: v.id('worlds'),
|
249 |
+
playerId,
|
250 |
+
},
|
251 |
+
handler: async (ctx, args) => {
|
252 |
+
// Walk the player's history in descending order, looking for a nonempty
|
253 |
+
// conversation.
|
254 |
+
const members = ctx.db
|
255 |
+
.query('participatedTogether')
|
256 |
+
.withIndex('playerHistory', (q) => q.eq('worldId', args.worldId).eq('player1', args.playerId))
|
257 |
+
.order('desc');
|
258 |
+
|
259 |
+
for await (const member of members) {
|
260 |
+
const conversation = await ctx.db
|
261 |
+
.query('archivedConversations')
|
262 |
+
.withIndex('worldId', (q) => q.eq('worldId', args.worldId).eq('id', member.conversationId))
|
263 |
+
.unique();
|
264 |
+
if (!conversation) {
|
265 |
+
throw new Error(`Invalid conversation ID: ${member.conversationId}`);
|
266 |
+
}
|
267 |
+
if (conversation.numMessages > 0) {
|
268 |
+
return conversation;
|
269 |
+
}
|
270 |
+
}
|
271 |
+
return null;
|
272 |
+
},
|
273 |
+
});
|