File size: 3,392 Bytes
90cbf22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df2ef4f
90cbf22
 
 
df2ef4f
 
 
90cbf22
 
 
 
 
 
 
df2ef4f
90cbf22
 
 
df2ef4f
 
 
90cbf22
 
 
 
 
 
 
df2ef4f
90cbf22
 
df2ef4f
 
 
 
90cbf22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df2ef4f
90cbf22
 
 
 
 
 
 
 
df2ef4f
 
 
90cbf22
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { ObjectType, v } from 'convex/values';
import { Conversation, serializedConversation } from './conversation';
import { Player, serializedPlayer } from './player';
import { Agent, serializedAgent } from './agent';
import { GameId, parseGameId, playerId } from './ids';
import { parseMap } from '../util/object';
import { GameCycle, gameCycleSchema } from './gameCycle';
import { Votes, VotesSchema } from './voting';

export const historicalLocations = v.array(
  v.object({
    playerId,
    location: v.bytes(),
  }),
);

export const serializedWorld = {
  nextId: v.number(),
  conversations: v.array(v.object(serializedConversation)),
  players: v.array(v.object(serializedPlayer)),
  playersInit: v.array(v.object(serializedPlayer)),
  agents: v.array(v.object(serializedAgent)),
  historicalLocations: v.optional(historicalLocations),
  gameCycle: v.object(gameCycleSchema),
  gameVotes: v.array(v.object(VotesSchema)),
  llmVotes: v.array(v.object(VotesSchema)),
  winner: v.optional(v.union(v.literal('werewolves'), v.literal('villagers')))
};
export type SerializedWorld = ObjectType<typeof serializedWorld>;

export class World {
  nextId: number;
  conversations: Map<GameId<'conversations'>, Conversation>;
  players: Map<GameId<'players'>, Player>;
  playersInit: Map<GameId<'players'>, Player>; // kept for voting purpose
  agents: Map<GameId<'agents'>, Agent>;
  historicalLocations?: Map<GameId<'players'>, ArrayBuffer>;
  gameCycle: GameCycle;
  gameVotes: Votes[];
  llmVotes: Votes[];
  winner?: 'werewolves' | 'villagers' | undefined

  constructor(serialized: SerializedWorld) {
    const { nextId, historicalLocations } = serialized;

    this.nextId = nextId;
    this.conversations = parseMap(serialized.conversations, Conversation, (c) => c.id);
    this.players = parseMap(serialized.players, Player, (p) => p.id);
    this.playersInit = parseMap(serialized.playersInit, Player, (p) => p.id);
    this.agents = parseMap(serialized.agents, Agent, (a) => a.id);
    this.gameCycle = new GameCycle(serialized.gameCycle);
    this.gameVotes = serialized.gameVotes.map((v) => new Votes(v));
    this.llmVotes = serialized.llmVotes.map((v) => new Votes(v));
    this.winner = serialized.winner;
    
    if (historicalLocations) {
      this.historicalLocations = new Map();
      for (const { playerId, location } of historicalLocations) {
        this.historicalLocations.set(parseGameId('players', playerId), location);
      }
    }
  }

  playerConversation(player: Player): Conversation | undefined {
    return [...this.conversations.values()].find((c) => c.participants.has(player.id));
  }

  serialize(): SerializedWorld {
    return {
      nextId: this.nextId,
      conversations: [...this.conversations.values()].map((c) => c.serialize()),
      players: [...this.players.values()].map((p) => p.serialize()),
      playersInit: [...this.playersInit.values()].map((p) => p.serialize()),
      agents: [...this.agents.values()].map((a) => a.serialize()),
      historicalLocations:
        this.historicalLocations &&
        [...this.historicalLocations.entries()].map(([playerId, location]) => ({
          playerId,
          location,
        })),
      gameCycle: this.gameCycle.serialize(),
      gameVotes: this.gameVotes.map((v) => v.serialize()),
      llmVotes: this.llmVotes.map((v) => v.serialize()),
      winner: this.winner,
    };
  }
}