+
+
Review Prompts
+
+
+
+
+
+
+ Prompt Name
+ ID
+ Active
+ Actions
+
+
+
+ {prompts?.map((row) => (
+
+ {row.promptName}
+ {row._id}
+ {row.isActive ? "Yes" : "No"}
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+};
+
+export default Page;
diff --git a/convex/_generated/api.d.ts b/convex/_generated/api.d.ts
index 0b5050f..96013c0 100644
--- a/convex/_generated/api.d.ts
+++ b/convex/_generated/api.d.ts
@@ -26,6 +26,7 @@ import type * as leaderboard from "../leaderboard.js";
import type * as maps from "../maps.js";
import type * as models from "../models.js";
import type * as playerresults from "../playerresults.js";
+import type * as prompts from "../prompts.js";
import type * as results from "../results.js";
import type * as scores from "../scores.js";
import type * as users from "../users.js";
@@ -50,6 +51,7 @@ declare const fullApi: ApiFromModules<{
maps: typeof maps;
models: typeof models;
playerresults: typeof playerresults;
+ prompts: typeof prompts;
results: typeof results;
scores: typeof scores;
users: typeof users;
diff --git a/convex/init.ts b/convex/init.ts
index 93852f5..defa092 100644
--- a/convex/init.ts
+++ b/convex/init.ts
@@ -5,5 +5,6 @@ export default internalMutation({
handler: async (ctx) => {
await ctx.runMutation(internal.maps.seedMaps);
await ctx.runMutation(internal.models.seedModels);
+ await ctx.runMutation(internal.prompts.seedPrompts);
},
});
diff --git a/convex/maps.ts b/convex/maps.ts
index 73b0964..78eb4f2 100644
--- a/convex/maps.ts
+++ b/convex/maps.ts
@@ -11,6 +11,7 @@ import { api, internal } from "./_generated/api";
import { runModel } from "../models";
import { getAuthUserId } from "@convex-dev/auth/server";
import { adminMutationBuilder } from "./users";
+import { Prompt } from "./prompts";
const LEVELS = [
{
@@ -300,9 +301,17 @@ export const playMapAction = internalAction({
return;
}
+ const activePromptQuery = await ctx.runQuery(api.prompts.getActivePrompt);
+ const activePrompt = activePromptQuery && activePromptQuery.prompt;
+
+ if (!activePrompt) {
+ throw new Error("Active prompt not found");
+ }
+
const { solution, reasoning, error } = await runModel(
args.modelId,
map.grid,
+ activePrompt,
);
await ctx.runMutation(internal.results.updateResult, {
@@ -322,12 +331,22 @@ export const testMap = action({
},
handler: async (ctx, args) => {
const isAdmin = await ctx.runQuery(api.users.isAdmin);
+ const activePrompt: Prompt = await ctx.runQuery(api.prompts.getActivePrompt);
+
if (!isAdmin) {
throw new Error("Test map is available only for admin");
}
- return await runModel(args.modelId, args.map);
+ if (!activePrompt) {
+ throw new Error("Active prompt not found");
+ }
+
+ return await runModel(
+ args.modelId,
+ args.map,
+ activePrompt.prompt,
+ );
},
});
@@ -350,9 +369,16 @@ export const testAIModel = action({
throw new Error("Map not found");
}
+ const activePrompt: Prompt = await ctx.runQuery(api.prompts.getActivePrompt);
+
+ if (!activePrompt) {
+ throw new Error("Active prompt not found");
+ }
+
const { solution, reasoning, error } = await runModel(
args.modelId,
map.grid,
+ activePrompt.prompt,
);
return {
diff --git a/convex/prompts.ts b/convex/prompts.ts
new file mode 100644
index 0000000..a76469e
--- /dev/null
+++ b/convex/prompts.ts
@@ -0,0 +1,186 @@
+import { v } from "convex/values";
+import { internalMutation, mutation, query } from "./_generated/server";
+import { Id } from "./_generated/dataModel";
+
+const defaultPrompt = `
+Your task is to play a game. We will give you a 2d array of characters that represent the game board. Before the game starts, you have these two tasks:
+
+1. Place two blocks ("B") in locations which maximize the player's survival.
+2. Place the player ("P") in a location which maximize the player's survival.
+
+# Placing Rules
+- You can not place blocks in locations already used by zombies or rocks.
+- You can not place the player in a location already used by a zombie or rock.
+- You can not place a block over the player or another block.
+- You must place both blocks and the player before starting the game.
+
+# Grid Descriptions
+The 2d Grid is made up of characters, where each character has a meaning.
+" " represents an empty space.
+"Z" represents a zombie.
+"R" represents rocks which zombies can not pass through and path finding will not allow them to go through.
+"P" represents the player, who cannot move. The player's goal is to throw popsickles at zombies before they reach them.
+"B" represents blocks that can be placed before the round begins to hinder the zombies.
+
+# Game Rules
+- The game is turn based.
+- At the start of the turn, the player (P) throws a popsickle at the closest zombie (using euclidean distance).
+- Popsickles deal 1 damage to zombies.
+- A zombie is removed from the game when its health reaches 0.
+- When all zombies are removed, the player wins.
+- If a zombie reaches a player, the player loses.
+
+# Zombie Rules
+- Zombies have 2 health.
+- Zombies can only move horizontally or vertically.
+- Zombies pathfinding will always be in the order of DOWN, LEFT, RIGHT, UP
+- Zombies can't move diagonally.
+- Zombies can't move through rocks.
+- Zombies can't move through each other.
+- Zombies always try to move towards the playing using BFS algorithm.
+
+# Player Rules
+- Players can not move.
+- Players throw one lollipops at the closest zombie at the start of each turn.
+
+# Placement Strategies
+
+- often it's good to wall off between the zombies and players if possible, this will slow the zombies down.
+- You should never put a player directly next to a zombie.
+- You should try to put blocks directly next to players
+- If the player is behind a choke point, blocking the path to the player is the best option.
+
+# Output Format
+
+- Assume a position on the 2d grid is always represented as [ROW, COL].
+- Your output should be a JSON object with the following format:
+
+{
+ "boxCoordinates": [[ROW, COL], [ROW, COL]],
+ "playerCoordinates": [ROW, COL]
+}
+
+## MOST IMPORTANT RULE
+
+- DO NOT TRY TO PUT A BLOCK OR PLAYER IN A LOCATION THAT IS ALREADY OCCUPIED
+
+`;
+
+export type Prompt = {
+ _id: Id<"prompts">;
+ _creationTime: number;
+ promptName: string;
+ prompt: string;
+ isActive: boolean;
+};
+
+export const getActivePrompt = query({
+ args: {},
+ handler: async (ctx): Promise