title: Piclets
emoji: 📷
colorFrom: yellow
colorTo: red
sdk: static
pinned: false
app_build_command: npm run build
app_file: dist/index.html
hf_oauth: true
hf_oauth_scopes:
- inference-api
Piclets
Monster collection & battle game leveraging Huggingface ZeroGPU spaces!
Battle System
Making everything LLM based!
The LLM gets the piclet descriptions, stats and action descriptions and then creates a JSON object conveying the status updates (including emojis for effects).
This should give the battles a unique "real" feel with interesting effective/ineffective interactions.
Status updates come with probabilities allowing for chance in the game while LLM sampling temperature is low.
The LLM backed has a dynamic setup so it can switch between providers, for now will use tencent/Hunyuan-Large
long term may switch to BlinkDL/RWKV-Gradio-2
.
Options for LLM backend:
- tencent/Hunyuan-Large (has been free for a while!)
- yuntian-deng/ChatGPT (say it will have short term availability)
- hysts/zephyr-7b (runs on zero-gpu)
- BlinkDL/RWKV-Gradio-2 (running on T4, never ran into rate limits)
- make my own Cohere space (20 generations per minute)
Old Battle System Ideas
How to handle combat?
I want a combat system that leverages the diversity of monsters and creativity of LLMs. I'd rather the game ran "offline" so without the need for non borwser-based computation.
I'd also like the combat to feel interesting with a diversity of Piclets being required. Now for most players they won't actually be able to catch that many Piclets (1 per day).
By interesting I mean the unique properties of the monster should shine through despite them not being explicitly coded for. The simplest version of this is having "weak against, robust against" lists and using a semantic encoder matches to define effectiveness.
I previously liked the idea of monsters having a "status" that would then effect combat, e.g. burning, bleading, sleeping, etc. This ofc also matches Pokemon though it does seem a little tricky to code and connect all of this.
Should also note that I can have a TON of data within my HF space so coding up a ton of status effect options is fine!
Combat Ideas
Semantic top-trumps
You attack with a given trait e.g. "flight" they then pick a counter monster to compare on that axis. The monster with the better semantic score wins.
A variation on this is each attack description vs the monsters description.
TBH 1v1 battles with just 1 move doesn't feel tactical enough.
True Pokemon
Just define a full running pokemon style game with the Pokemon suite of moves. Could even extend to include special abilities like being invulnerable to drain, can't be switched out, etc.
This would mean abilities would be defined ahead of time and picked for the monster.
Nice thing is that this would balance the same way and have a high complexity ceiling. The bad thing is that this could actually be extremely difficult to implement, likely best done by just emulating the underlying game with modified sprites & names for the monster.
LLM powered Pokemon
Leverage free LLM spaces (maybe RWKV?) to have the LLM generate the outcomes of the different action. Include updating free-form status descriptions.
This should give a consistent range of effects without requiring complex code.
The issue here is with accessing the LLM responses. This would have to rely on non zero-GPU spaces to get the response rate required.
Semantic Pokemon
Define pokemon style moves with keywords defining strong against, weak against and action special cases.
This is effectively doing what "LLM powered Pokemon" would do but offline.
Different effects have different probabilities. Statuses are applied and semanticly matched into hard coded ones.
e.g. "Dazed" is similar to "Confusion" so gets the "Confusion" effect
Combat Choice
I think Semantic Pokemon is the best choice as it gives great variety while being runnable offline.
To put this in more detail...
- monsters each have lists of keywords for "weak to" and "robust to" for effective/ineffective
- each action has hard coded effects with special cases for certain monsters
- monster actions are colored to indicate attack/buff/debuff/special
When hard coding effects the action can apply descriptors to the enemy, these then interact with game-level effects and the monsters own effective/ineffective. Previously I did like the emoji setup as it was quick to communicate... but it often wasn't high level enough. I'm hopeful that high level descriptors + a semantic encoder will give more matches than previously.
So the monster schema will have:
"robust against": {"type": "string", "description": "A brief description of things the monster is robust to"},
"weak against": {"type": "string", "description": "A brief description of things the monster is weak to"},
Then for the actions:
"attack": {
"name": "...",
"description": "...",
"damage": "likert",
"accuracy": "likert",
"inflictStatus": "...",
}
Keyword based
Another option is to just have claude create a really extensive keyword system to analyze action descriptions and make a series of classifiers based on that. I have had success with this before and its nice to think I then only have to handle the action descriptions. Then I could add back the old Piclet types to pair up with this. Plus then include an emoji for each action to give a cool animation effect!
The bad thing here is that I am having to hand-code a battle system which I didn't really want to do.
Svelte + TS + Vite
This template should help get you started developing with Svelte and TypeScript in Vite.
Recommended IDE Setup
Need an official Svelte framework?
Check out SvelteKit, which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
Technical considerations
Why use this over SvelteKit?
- It brings its own routing solution which might not be preferable for some users.
- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other create-vite
templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
Why global.d.ts
instead of compilerOptions.types
inside jsconfig.json
or tsconfig.json
?
Setting compilerOptions.types
shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding svelte
and vite/client
type information.
Why include .vscode/extensions.json
?
Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
Why enable allowJs
in the TS template?
While allowJs: false
would indeed prevent the use of .js
files in the project, it does not prevent the use of JavaScript syntax in .svelte
files. In addition, it would force checkJs: false
, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.
Why is HMR not preserving my local component state?
HMR state preservation comes with a number of gotchas! It has been disabled by default in both svelte-hmr
and @sveltejs/vite-plugin-svelte
due to its often surprising behavior. You can read the details here.
If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
// store.ts
// An extremely simple external store
import { writable } from "svelte/store";
export default writable(0);