Skip to content

Commit

Permalink
adding visualizer
Browse files Browse the repository at this point in the history
  • Loading branch information
webdevcody committed Oct 16, 2024
1 parent 60d0649 commit 4cff246
Show file tree
Hide file tree
Showing 21 changed files with 119 additions and 12 deletions.
3 changes: 1 addition & 2 deletions app/games/[gameId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"use client";

import { Map } from "@/app/map";
import { api } from "@/convex/_generated/api";
import { Id } from "@/convex/_generated/dataModel";
import { useQuery } from "convex/react";
Expand All @@ -15,7 +14,7 @@ export default function GamePage({ params }: { params: { gameId: string } }) {
});

return (
<div className="container mx-auto min-h-screen flex flex-col items-center pt-12 gap-8">
<div className="container mx-auto min-h-screen flex flex-col items-center py-12 pb-24 gap-8">
<h1>Game {params.gameId}</h1>
<h2>Model: {game?.modelId}</h2>

Expand Down
4 changes: 2 additions & 2 deletions app/games/[gameId]/result.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { Map } from "@/app/map";
import { Visualizer } from "./visualizer";
import { api } from "@/convex/_generated/api";
import { Doc } from "@/convex/_generated/dataModel";
import { useQuery } from "convex/react";
Expand All @@ -19,7 +19,7 @@ export const Result = ({ result }: { result: Doc<"results"> }) => {
return (
<div className="flex items-center gap-8" key={map._id}>
<div>Level {map.level}</div>
<Map map={map.grid} />
<Visualizer map={result.map} />
<div
className={`font-bold ${result.isWin ? "text-green-500" : "text-red-500"}`}
>
Expand Down
50 changes: 50 additions & 0 deletions app/games/[gameId]/visualizer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Button } from "@/components/ui/button";
import { ZombieSurvival } from "@/simulators/zombie-survival";
import { useRef, useState } from "react";

const REPLAY_SPEED = 600;

export function Visualizer({ map }: { map: string[][] }) {
const simulator = useRef<ZombieSurvival | null>(null);
const interval = useRef<NodeJS.Timeout | null>(null);
const [isRunning, setIsRunning] = useState(false);
const [mapState, setMapState] = useState(map);

return (
<div>
{mapState.map((row, y) => (
<div key={y} className="flex">
{row.map((cell, x) => (
<div
key={x}
className={`size-8 border flex items-center justify-center text-2xl bg-slate-950`}
>
{cell}
</div>
))}
</div>
))}
<Button
onClick={() => {
const clonedMap = JSON.parse(JSON.stringify(map));
simulator.current = new ZombieSurvival(clonedMap);
setMapState(simulator.current!.getState());
setIsRunning(true);
interval.current = setInterval(() => {
if (simulator.current!.finished()) {
clearInterval(interval.current!);
interval.current = null;
setIsRunning(false);
return;
}
simulator.current!.step();
setMapState(simulator.current!.getState());
}, REPLAY_SPEED);
}}
disabled={isRunning}
>
Play
</Button>
</div>
);
}
46 changes: 46 additions & 0 deletions convex/maps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,52 @@ const MAPS = [
width: 5,
height: 5,
},
{
level: 3,
grid: [
["Z", " ", " ", "R", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", "Z", " "],
[" ", " ", " ", " ", " ", " ", " "],
[" ", "R", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", "R", " ", " "],
],
width: 7,
height: 7,
},
{
level: 4,
grid: [
[" ", "Z", " ", " ", "R", " ", " "],
[" ", " ", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", "Z"],
[" ", " ", "R", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", " "],
],
width: 7,
height: 7,
},
{
level: 5,
grid: [
[" ", " ", " ", " ", "R", "Z", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
["Z", " ", " ", " ", " ", "R", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", "R", " ", " ", " ", " ", "Z", " "],
[" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
[" ", " ", "R", " ", " ", " ", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", "Z", " ", " ", " ", " "],
["B", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
[" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
["Z", " ", " ", " ", "Z", " ", " ", " ", " ", " ", "Z"],
],
width: 11,
height: 11,
},
];

export const seedMaps = internalMutation({
Expand Down
16 changes: 12 additions & 4 deletions convex/openai.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import OpenAI from "openai";
import { action, internalAction } from "./_generated/server";
import { internalAction } from "./_generated/server";
import { v } from "convex/values";
import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/zod";
import { api, internal } from "./_generated/api";
import { Doc } from "./_generated/dataModel";
import { ZombieSurvival } from "../simulators/zombie-survival";

const ResponseSchema = z.object({
map: z.array(z.array(z.string())),
Expand Down Expand Up @@ -68,7 +69,9 @@ export const playMapAction = internalAction({
"P" represents the player, who cannot move. The player's goal is to shoot and kill zombies before they reach them.
"B" represents blocks that can be placed before the round begins to hinder the zombies. You can place up to two blocks on the map.
Your goal is to place the player ("P") and two blocks ("B") in locations that maximize the player's survival by delaying the zombies' approach while allowing the player clear lines of sight to shoot them before they get too close.
Returning a 2d grid with the player and blocks placed in the optimal locations, with the coordinates player ("P") and the blocks ("B"), also provide reasoning for the choices.`,
Returning a 2d grid with the player and blocks placed in the optimal locations, with the coordinates player ("P") and the blocks ("B"), also provide reasoning for the choices.
You can't replace rocks R or zombies Z with blocks. If there is no room to place a block, do not place any.`,
},
{
role: "user",
Expand All @@ -80,12 +83,17 @@ export const playMapAction = internalAction({

const response = completion.choices[0].message;
if (response.parsed) {
// TODO: run simulation here to determine if win is true or false
const game = new ZombieSurvival(response.parsed.map);
while (!game.finished()) {
game.step();
}
const isWin = !game.getPlayer().dead();

await ctx.runMutation(internal.results.updateResult, {
resultId,
isWin: true,
isWin,
reasoning: response.parsed.reasoning,
map: response.parsed.map,
});
} else if (response.refusal) {
const refusal_res = response.refusal;
Expand Down
3 changes: 3 additions & 0 deletions convex/results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const createInitialResult = internalMutation({
reasoning: "",
status: "inProgress",
isWin: false,
map: [],
});
},
});
Expand All @@ -35,6 +36,7 @@ export const updateResult = internalMutation({
resultId: v.id("results"),
isWin: v.boolean(),
reasoning: v.string(),
map: v.array(v.array(v.string())),
},
handler: async (ctx, args) => {
const result = await ctx.db.get(args.resultId);
Expand All @@ -47,6 +49,7 @@ export const updateResult = internalMutation({
isWin: args.isWin,
reasoning: args.reasoning,
status: "completed",
map: args.map,
});

const game = await ctx.db.get(result.gameId);
Expand Down
1 change: 1 addition & 0 deletions convex/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default defineSchema({
level: v.number(),
isWin: v.boolean(),
reasoning: v.string(),
map: v.array(v.array(v.string())),
status: v.union(v.literal("inProgress"), v.literal("completed")),
}).index("by_gameId_level", ["gameId", "level"]),
});
2 changes: 1 addition & 1 deletion convex/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@
"isolatedModules": true,
"noEmit": true
},
"include": ["./**/*"],
"include": ["./**/*", "../simulators/**/*"],
"exclude": ["./_generated"]
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Entity } from "./entities/Entity";
import { Player } from "./entities/Player";
import { Rock } from "./entities/Rock";
import { Zombie } from "./entities/Zombie";
import { entityAt } from "./lib/entity-at";
import { entityAt } from "./lib/entityAt";

export class ZombieSurvival {
public readonly boardHeight: number;
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Entity, EntityType } from "./Entity";
import { Position } from "../Position";
import { ZombieSurvival } from "../ZombieSurvival";
import { closestEntity } from "../lib/closest-entity";
import { closestEntity } from "../lib/closestEntity";

export class Player extends Entity {
public static Destructible = true;
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Direction, allDirections, move } from "../Direction";
import { Entity, EntityType } from "./Entity";
import { Position } from "../Position";
import { ZombieSurvival } from "../ZombieSurvival";
import { entityAt } from "../lib/entity-at";
import { entityAt } from "../lib/entityAt";
import { pathfinder } from "../lib/pathfinder";

export class Zombie extends Entity {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 4cff246

Please sign in to comment.