diff --git a/README.md b/README.md index 0cb944b..8bb7448 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,51 @@ The application will be available at [http://localhost:3000](http://localhost:30 - `contracts/`: Solidity smart contracts for the Metarchy ecosystem. - `data/`: JSON storage for games and citizens (mounted as a volume in Docker). +## Update Log & Versions + +### v1.6.0 (Strategic Mobility - Current) +- **Teleportation System**: Relocation action cards enable tactical repositioning of actors during Phase 3 Step 3. +- **Resource Exchange**: Strategic resource swapping with opponents using Exchange cards in Phase 3 Step 4. +- **Visual Clarity**: White glow indicators on actors eligible for teleportation with subtle arrow button UI. +- **Step Navigation**: Clear "Start [Action]" buttons guide players through each Phase 3 sub-step. +- **Empty State Messaging**: Prominent "NO ACTION CARDS" notification when hand is empty for current step. + +### v1.5.0 (Tactical Refinement) +- **4-Step Action Phase**: Strict sequential workflow for Phase 3: Bidding → Stop Locations → Relocation → Exchange. +- **Bidding Lock**: Material resource bets can only be placed/modified during Step 1; visible but immutable in subsequent steps. +- **Visual Disable State**: Grayscale/desaturated effect applied to disabled locations and all actors within them. +- **Adaptive Card Filtering**: Action cards panel dynamically filters by step type with fallback "no action cards" message. +- **Compact Card View**: Streamlined UI for Relocation and Exchange steps with hidden descriptions. + +### v1.4.0 (Analytics & Governance) +- **Live Telemetry**: Real-time auto-updating Admin Dashboard with `Live Link` status. +- **Analytical Logs**: Standardized `[ID] [Time UTC] Action` format for high-precision auditing. +- **Session Intelligence**: Real-time citizen `Online/Offline` status tracking and heartbeats. +- **Strategic Recall**: Added the ability to recall actors and tokens during the distribution phase. + +### v1.3.1 (Tactical Polish) +- **AI Emulation**: Realistic "thinking" delays for Viper and Ghost opponent actions. +- **RSP Intelligence**: Smart filtering of used tokens to prevent duplicate deployments. +- **Phase Lockdown**: Adaptive UI that prevents advancing until all tactical units are placed. + +### v1.3.0 (Immersion & UX) +- **Navigable Map**: High-performance "Drag-to-Move" map panning. +- **Action Zoom**: Dynamic 1.6x zoom scaling during critical action phases. +- **Room Synthesis**: Random thematic name generator for unique game sessions. + +### v1.2.0 (Identity & Persistence) +- **Decentralized Identity**: Integrated Citizen ID creation and MetaMask session management. +- **Global Lobby**: Multi-room game discovery with waiting room simulations. +- **FileSystem Persistence**: Robust JSON-based storage for long-running game sessions. + +### v1.1.0 (Networking Core) +- **Dynamic Routing**: Shifted to UUID-based session addressing at `/game/board/[id]`. +- **API Foundation**: Initial REST architecture for game state and citizen records. + +### v1.0.0 (Neural Genesis) +- **Core Engine**: Hex-based map and four initial Actor classes (Politician, Robot, Scientist, Artist). +- **HUD System**: Early placement markers and resource tracking. + ## License This project is licensed under the MIT License. diff --git a/frontend/.vscode/settings.json b/frontend/.vscode/settings.json new file mode 100644 index 0000000..cb19a07 --- /dev/null +++ b/frontend/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "css.lint.unknownAtRules": "ignore" +} \ No newline at end of file diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..a08de09 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,53 @@ +# Metarchy Frontend - Development Status + +**Last Updated:** February 2, 2026 + +## 🚀 Recent Updates (Session Handover) + +We have successfully implemented the **Conflict Phase (Phase 4)** with high-fidelity visuals and refined game logic. + +### ✅ Completed Features +1. **Conflict Phase UI** + - **Conflicts Sidebar**: A persistent, collapsible sidebar that lists active conflicts. Visually integrates the Phase 2 "Actor Orb" (Player) and Phase 3 "HUD Marker" (Opponent) styles. + - **Resolution Arena (`ConflictResolutionView`)**: A premium close-up modal featuring: + - Full-screen location concept art backdrops. + - Full-body actor illustrations with team tinting. + - Animated reveal sequences (Entrance, Reveal, Results) using `framer-motion`. + +2. **Logic Refinements** + - **Strict Role-Based Conflicts**: Conflicts now **only** occur between actors of the **same role** (e.g., Politician vs Politician). Matches based on RSP tokens alone (e.g., Rock vs Rock) are ignored. + - **Multi-Conflict Locations**: A single location can now host multiple distinct conflicts (e.g., a Robot battle and a Scientist battle at the same "Square"). + - **Filtering**: Resolved conflicts effectively disappear from the active list to prevent infinite loops. + +3. **Bug Fixes** + - Fixed missing Player Avatars/Names in the Sidebar by correctly mapping to `MY_ACTORS`. + - Fixed "Random Conflicts" by ensuring `actorType` is recorded during placement in `GameBoardPage.tsx`. + - Hidden opponent Bid Icons in the Sidebar (requested change). + +--- + +## 🛠 Key Technical Notes for Next Session + +* **Conflict Detection Logic**: + - Located in `GameBoardPage.tsx` -> `activeConflicts` useMemo. + - It iterates through placed actors and explicitly checks `a.actorType === playerActorRaw.actorType`. + - **Important**: The `placedActors` state has been patched to include `actorType` during `handleRSPSelect`. Ensure any *new* placement mechanics also include this property. + +* **Visual Assets**: + - Location backgrounds are pulled from `/public/Locations closeups/`. + - Actor images are mapped via `MY_ACTORS` or `PLAYERS` arrays. + +* **State Management**: + - `activeConflictLocId`: Tracks which specific conflict is currently being viewed in the Arena. It uses a composite ID format: `${locId}_${actorType}` (e.g., `square_politician`). + - `resolvedConflicts`: Array of composite IDs that have been finished. + +## 📋 Next Steps + +1. **Phase 5 (Resolution / End Game)**: + - Implement the final scoring or transition after conflicts are resolved. + - Handle the "Double Prize" logic verification fully (currently simulated). +2. **Sound Effects**: + - Add SFX for "VS" slam, Card Reveal, and Victory/Defeat states. +3. **Edge Cases**: + - Verify "Draw" mechanics with diverse bid types (Star/Recycle). + - detailed testing of the "Restart" flow for Energy bids. diff --git a/frontend/app/admin/citizens/page.tsx b/frontend/app/admin/citizens/page.tsx index d01a048..1a013eb 100644 --- a/frontend/app/admin/citizens/page.tsx +++ b/frontend/app/admin/citizens/page.tsx @@ -25,6 +25,8 @@ export default function AdminCitizensPage() { useEffect(() => { fetchCitizens(); + const interval = setInterval(fetchCitizens, 5000); + return () => clearInterval(interval); }, []); const handleDelete = async (id: string) => { @@ -74,9 +76,15 @@ export default function AdminCitizensPage() {

Citizen Management

Manage registered network participants

-
- Authorized Residents - {citizens.length} +
+
+ + Resident Uplink Live +
+
+ Authorized Residents + {citizens.length} +
diff --git a/frontend/app/admin/games/page.tsx b/frontend/app/admin/games/page.tsx index 2c364b9..566f914 100644 --- a/frontend/app/admin/games/page.tsx +++ b/frontend/app/admin/games/page.tsx @@ -2,11 +2,12 @@ import React, { useState, useEffect } from 'react'; import { Game } from '@/lib/types'; -import { Trash2, Edit2, AlertCircle, CheckCircle2, Clock } from 'lucide-react'; +import { Trash2, Edit2, AlertCircle, CheckCircle2, Clock, ScrollText, X } from 'lucide-react'; export default function AdminGamesPage() { const [games, setGames] = useState([]); const [loading, setLoading] = useState(true); + const [selectedGameId, setSelectedGameId] = useState(null); const [message, setMessage] = useState<{ text: string, type: 'success' | 'error' } | null>(null); const fetchGames = async () => { @@ -25,8 +26,13 @@ export default function AdminGamesPage() { useEffect(() => { fetchGames(); + // Auto-refresh every 3 seconds for live monitoring + const interval = setInterval(fetchGames, 3000); + return () => clearInterval(interval); }, []); + const selectedGame = games.find(g => g.id === selectedGameId); + const handleDelete = async (id: string) => { if (!confirm("Are you sure you want to delete this game? This action cannot be undone.")) return; @@ -82,9 +88,15 @@ export default function AdminGamesPage() {

Game Management

Oversee and control active game sessions

-
- Total Games - {games.length} +
+
+ + Live Neural Link Established +
+
+ Total Nodes + {games.length} +
@@ -96,7 +108,7 @@ export default function AdminGamesPage() {
)} -
+
@@ -158,13 +170,22 @@ export default function AdminGamesPage() { )) @@ -172,6 +193,58 @@ export default function AdminGamesPage() {
- +
+ + +
+ + {/* Log Viewer Modal */} + {selectedGameId && ( +
+
+
+
+
+

Game Command History

+

{selectedGameId}

+
+
+ + Live Link +
+
+ +
+ +
+ {selectedGame && selectedGame.logs && selectedGame.logs.length > 0 ? ( + [...selectedGame.logs].reverse().map((log, i) => ( +
+ #{String(selectedGame.logs.length - i).padStart(3, '0')} +

+ {log} +

+
+ )) + ) : ( +
+

No telemetry data recorded for this session

+
+ )} +
+ + +
+
+ )}
); } diff --git a/frontend/app/api/citizen/route.ts b/frontend/app/api/citizen/route.ts index 6f95174..b2f28ea 100644 --- a/frontend/app/api/citizen/route.ts +++ b/frontend/app/api/citizen/route.ts @@ -13,6 +13,8 @@ interface Citizen { citizenId: string; joinedAt: string; avatar?: string; + isOnline: boolean; + lastActive: string; } // Helper to ensure DB exists @@ -90,7 +92,9 @@ export async function POST(request: NextRequest) { name, citizenId: newId, joinedAt: new Date().toISOString(), - avatar: "/avatars/golden_avatar.png" + avatar: "/avatars/golden_avatar.png", + isOnline: true, + lastActive: new Date().toISOString() }; citizens.push(newCitizen); @@ -101,3 +105,31 @@ export async function POST(request: NextRequest) { return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 }); } } + +// PUT: Update citizen status (online/offline) +export async function PUT(request: NextRequest) { + try { + const body = await request.json(); + const { address, status } = body; + + if (!address) { + return NextResponse.json({ error: 'Address required' }, { status: 400 }); + } + + const citizens = readDB(); + const index = citizens.findIndex(c => c.address.toLowerCase() === address.toLowerCase()); + + if (index === -1) { + return NextResponse.json({ error: 'Citizen not found' }, { status: 404 }); + } + + citizens[index].isOnline = status === 'online'; + citizens[index].lastActive = new Date().toISOString(); + + writeDB(citizens); + + return NextResponse.json(citizens[index]); + } catch (e) { + return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 }); + } +} diff --git a/frontend/app/api/games/[id]/ready/route.ts b/frontend/app/api/games/[id]/ready/route.ts index 5c24665..41703fd 100644 --- a/frontend/app/api/games/[id]/ready/route.ts +++ b/frontend/app/api/games/[id]/ready/route.ts @@ -36,12 +36,8 @@ export async function POST(request: NextRequest, { params }: { params: { id: str let updates: any = { players: game.players }; if (allReady && isLobbyFull && game.status === 'waiting') { - updates.status = 'starting'; - updates.startTime = Date.now() + 10000; // 10 seconds from now - } else if ((!allReady || !isLobbyFull) && game.status === 'starting') { - // Cancel countdown if someone un-readies - updates.status = 'waiting'; - updates.startTime = undefined; + updates.status = 'playing'; + updates.startTime = Date.now(); } const updatedGame = gameService.update(params.id, updates); diff --git a/frontend/app/api/games/[id]/route.ts b/frontend/app/api/games/[id]/route.ts index 8fa5ef8..fa5d036 100644 --- a/frontend/app/api/games/[id]/route.ts +++ b/frontend/app/api/games/[id]/route.ts @@ -1,5 +1,6 @@ import { NextRequest, NextResponse } from 'next/server'; import { gameService } from '@/lib/gameService'; +import { formatLog } from '@/lib/logUtils'; export async function GET(request: NextRequest, { params }: { params: { id: string } }) { try { @@ -28,10 +29,17 @@ export async function PUT(request: NextRequest, { params }: { params: { id: stri return NextResponse.json({ error: 'Player data required' }, { status: 400 }); } try { + const logs = [...(game.logs || []), formatLog(game.displayId || game.id, `${player.name} joined`)]; game = gameService.addPlayer(params.id, { ...player, joinedAt: Date.now() }) || game; + game = gameService.update(params.id, { logs }) || game; } catch (e: any) { return NextResponse.json({ error: e.message }, { status: 400 }); } + } else if (action === 'add-log' && body.message) { + const formattedMsg = formatLog(game.displayId || game.id, body.message); + game = gameService.update(params.id, { + logs: [...(game.logs || []), formattedMsg] + }) || game; } else if (action === 'update' && updates) { game = gameService.update(params.id, updates) || game; } diff --git a/frontend/app/api/games/route.ts b/frontend/app/api/games/route.ts index 752d0cb..8ff5bd6 100644 --- a/frontend/app/api/games/route.ts +++ b/frontend/app/api/games/route.ts @@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server'; import { gameService } from '@/lib/gameService'; import { Game } from '@/lib/types'; import { v4 as uuidv4 } from 'uuid'; +import { formatLog } from '@/lib/logUtils'; export async function GET() { try { @@ -21,8 +22,13 @@ export async function POST(request: NextRequest) { return NextResponse.json({ error: 'Missing required fields' }, { status: 400 }); } + const allGames = gameService.getAll(); + const displayId = (allGames.length + 1).toString().padStart(3, '0'); + + const gameId = id || uuidv4(); const newGame: Game = { - id: id || uuidv4(), + id: gameId, + displayId, roomId: roomName, status: 'waiting', isPrivate: !!isPrivate, @@ -32,7 +38,7 @@ export async function POST(request: NextRequest) { ], maxPlayers: maxPlayers || 4, bidAmount: 0, - logs: [`Game created by ${hostPlayer.name}`], + logs: [formatLog(displayId, `GAME CREATED BY ${hostPlayer.name}`)], transactions: [], messages: [] }; diff --git a/frontend/app/game/board/[id]/page.tsx b/frontend/app/game/board/[id]/page.tsx index d138a6d..c51419f 100644 --- a/frontend/app/game/board/[id]/page.tsx +++ b/frontend/app/game/board/[id]/page.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect, useMemo } from 'react'; import Image from 'next/image'; -import { ChevronUp, ChevronDown, Check, X, Box, Zap, Recycle } from "lucide-react"; +import { ChevronUp, ChevronDown, Check, X } from "lucide-react"; import { useGameState } from "@/context/GameStateContext"; import { TooltipProvider } from "@/context/TooltipContext"; import CursorTooltip from "@/components/ui/CursorTooltip"; @@ -15,16 +15,21 @@ import MapContainer from "@/components/game/MapContainer"; import GameHeader from "@/components/game/GameHeader"; import GameResources from "@/components/game/GameResources"; import RSPRadialMenu from "@/components/game/RSPRadialMenu"; +import ActionCardsPanel from "@/components/game/ActionCardsPanel"; +import ExchangeModal from "@/components/game/ExchangeModal"; +import ConflictsSidebar from "@/components/game/ConflictsSidebar"; +import ConflictResolutionView, { ConflictResult } from "@/components/game/ConflictResolutionView"; +import { formatLog } from '@/lib/logUtils'; // Constants import { EVENTS, LOCATIONS, ACTION_CARDS, getConflicts, ALLOWED_MOVES } from '@/data/gameConstants'; // --- MOCK DATA FOR ACTORS (Assuming these will come from State/Wallet later) --- const ACTOR_TYPES: { [key: string]: { name: string, avatar: string } } = { - "politician": { name: "Politician", avatar: "/actors/actor_scientist.png" }, - "robot": { name: "Robot", avatar: "/actors/actor_politician.png" }, - "scientist": { name: "Scientist", avatar: "/actors/actor_robot.png" }, - "artist": { name: "Artist", avatar: "/actors/actor_artist.png" } + "politician": { name: "Politician", avatar: "/actors/Polotican.png" }, + "robot": { name: "Robot", avatar: "/actors/Robot.png" }, + "scientist": { name: "Scientist", avatar: "/actors/Scientist.png" }, + "artist": { name: "Artist", avatar: "/actors/Artist.png" } }; const MY_ACTORS = [ @@ -40,6 +45,25 @@ const PLAYERS = [ { id: 'p4', name: 'Union', avatar: '/avatars/avatar_union.png', color: '#4444ff' }, ]; +const AUTO_PLACEMENTS = [ + // Viper (p2) + { actorId: "v1", playerId: "p2", locId: "square", type: "rock", isOpponent: true, name: "Politician", actorType: "politician", avatar: "/actors/Polotican.png", bid: "product" }, + { actorId: "v2", playerId: "p2", locId: "factory", type: "paper", isOpponent: true, name: "Robot", actorType: "robot", avatar: "/actors/Robot.png", bid: "energy" }, + { actorId: "v3", playerId: "p2", locId: "university", type: "scissors", isOpponent: true, name: "Scientist", actorType: "scientist", avatar: "/actors/Scientist.png" }, + { actorId: "v4", playerId: "p2", locId: "theatre", type: "rock", isOpponent: true, name: "Artist", actorType: "artist", avatar: "/actors/Artist.png" }, + // Ghost (p3) + { actorId: "g1", playerId: "p3", locId: "university", type: "scissors", isOpponent: true, name: "Politician", actorType: "politician", avatar: "/actors/Polotican.png", bid: "recycle" }, + { actorId: "g2", playerId: "p3", locId: "dump", type: "rock", isOpponent: true, name: "Robot", actorType: "robot", avatar: "/actors/Robot.png" }, + { actorId: "g3", playerId: "p3", locId: "theatre", type: "paper", isOpponent: true, name: "Scientist", actorType: "scientist", avatar: "/actors/Scientist.png" }, + { actorId: "g4", playerId: "p3", locId: "square", type: "scissors", isOpponent: true, name: "Artist", actorType: "artist", avatar: "/actors/Artist.png" }, +]; + +interface OpponentData { + id: string; + resources: Record; + cards: Record; +} + export default function GameBoardPage() { const { id } = useParams(); // --- State Management --- @@ -47,6 +71,25 @@ export default function GameBoardPage() { const [game, setGame] = useState(null); const [phase, setPhase] = useState(2); // Game starts at T1P2 const [turn, setTurn] = useState(1); + const [opponentsReady, setOpponentsReady] = useState(false); + const [opponentsData, setOpponentsData] = useState>({}); + + // Initialize opponents data dynamically + useEffect(() => { + const initialOpponents: Record = {}; + PLAYERS.forEach(opp => { + initialOpponents[opp.id] = { + id: opp.id, + resources: { + gato: 1000, + product: 1, energy: 1, recycle: 1, + power: 0, art: 0, knowledge: 0, glory: 0, vp: 0 + }, + cards: {} + }; + }); + setOpponentsData(initialOpponents); + }, []); // Fetch Specific Game Data useEffect(() => { @@ -70,6 +113,71 @@ export default function GameBoardPage() { return () => clearInterval(interval); }, [id]); + // --- Opponent Emulation --- + useEffect(() => { + if (phase === 2 && !opponentsReady && game) { + triggerOpponentPlacements(); + } + }, [phase, game, opponentsReady]); + + const triggerOpponentPlacements = async () => { + if (!game) return; + setOpponentsReady(true); + + await new Promise(r => setTimeout(r, 1500)); + + const opponentActions = AUTO_PLACEMENTS; + + for (const action of opponentActions) { + setPlacedActors(prev => { + if (prev.some(p => p.actorId === action.actorId)) return prev; + return [...prev, action]; + }); + + // Update opponent resources if bid is placed + if (action.bid) { + setOpponentsData(prev => { + const next = { ...prev }; + if (!next[action.playerId]) return prev; + const oppRes = { ...next[action.playerId].resources }; + oppRes[action.bid] = Math.max(0, (oppRes[action.bid] || 0) - 1); + next[action.playerId] = { ...next[action.playerId], resources: oppRes }; + return next; + }); + } + + const playerName = PLAYERS.find(p => p.id === action.playerId)?.name || action.playerId; + await addLog(`${playerName} placed ${action.name} with ${action.type.toUpperCase()} to ${action.locId}`); + + await new Promise(r => setTimeout(r, 600)); // Increased delay for stability + } + + await addLog("Viper (p2) ready"); + await new Promise(r => setTimeout(r, 600)); + await addLog("Ghost (p3) ready"); + }; + + const addLog = async (msg: string) => { + if (!id || !game) return; + + // Optimistically update local state with a functional update to avoid stale closures + const formattedMsg = formatLog(game.displayId || game.id as string, msg); + setGame((prev: any) => ({ + ...prev, + logs: [...(prev?.logs || []), formattedMsg] + })); + + try { + await fetch(`/api/games/${id}`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ action: 'add-log', message: msg }) + }); + } catch (e) { + console.error("Failed to sync log", e); + } + }; + console.log("GameBoardPage Rendering, Phase:", phase, "Turn:", turn); // Phase 1: Events @@ -89,12 +197,141 @@ export default function GameBoardPage() { const [activeCardId, setActiveCardId] = useState(null); const [activatedCards, setActivatedCards] = useState([]); const [disabledLocations, setDisabledLocations] = useState([]); - const [exchangeTarget, setExchangeTarget] = useState<{ id: string, x: number, y: number } | null>(null); + const [exchangeTarget, setExchangeTarget] = useState<{ id: string, name: string, x: number, y: number } | null>(null); const [teleportSource, setTeleportSource] = useState(null); + const [biddingActorId, setBiddingActorId] = useState(null); + const [p3Step, setP3Step] = useState<1 | 2 | 3 | 4>(1); // 1: Bidding, 2: Stop, 3: Teleport, 4: Exchange + const [actionHand, setActionHand] = useState([]); + + const filteredActionHand = useMemo(() => { + if (p3Step === 1) return []; + if (p3Step === 2) return actionHand.filter(c => c.type === 'location'); + if (p3Step === 3) return actionHand.filter(c => c.id.includes('relocation') || c.id.includes('teleport')); + if (p3Step === 4) return actionHand.filter(c => c.id.includes('change_values') || c.id.includes('exchange')); + return []; + }, [p3Step, actionHand]); + + // Count available teleport cards + const teleportCardsCount = useMemo(() => { + return actionHand.filter(c => c.id.includes('relocation') || c.id.includes('teleport')).length; + }, [actionHand]); + + // Count available exchange cards + const exchangeCardsCount = useMemo(() => { + return actionHand.filter(c => c.id.includes('change_values') || c.id.includes('exchange')).length; + }, [actionHand]); + // Phase 4: Conflicts - const [activeConflictId, setActiveConflictId] = useState(null); - const [conflictState, setConflictState] = useState<'choose' | 'result'>('choose'); + const [activeConflictLocId, setActiveConflictLocId] = useState(null); + const [resolvedConflicts, setResolvedConflicts] = useState([]); + + // Conflict Detection Logic (Local override of gameConstants version) + const activeConflicts = useMemo(() => { + if (phase !== 4) return []; + + const locsWithActors: { [key: string]: any[] } = {}; + placedActors.forEach(p => { + if (!locsWithActors[p.locId]) locsWithActors[p.locId] = []; + locsWithActors[p.locId].push(p); + }); + + const conflicts: any[] = []; + Object.entries(locsWithActors).forEach(([locId, actors]) => { + // if (activeConflictLocId === locId) return; // Removed to allow all conflicts + + // Conflict if > 1 actor AND location not disabled + // Conflict if > 1 actor AND location not disabled + if (actors.length > 1 && !disabledLocations.includes(locId)) { + + // Find all player actors at this location + const myActorsAtLoc = actors.filter(a => a.playerId === 'p1'); + + myActorsAtLoc.forEach(playerActorRaw => { + // Find opponents of the SAME ACTOR TYPE (Role vs Role) + const sameTypeOpponents = actors.filter(a => + a.playerId !== 'p1' && + a.actorType === playerActorRaw.actorType + ); + + if (sameTypeOpponents.length > 0) { + // Enhance playerActor with full details including avatar + const playerActorSource = MY_ACTORS.find(p => p.id === playerActorRaw.actorId); + const playerActor = { + ...playerActorRaw, + avatar: playerActorSource?.avatar || '', + name: playerActorSource?.name || 'My Actor', + type: playerActorSource?.type || playerActorRaw.type || 'unknown' + }; + + const locDef = LOCATIONS.find(l => l.id === locId); + + // Unique ID per conflict instance (Location + ActorType) + const uniqueConflictId = `${locId}_${playerActor.type}`; + + // Don't duplicate if already added OR resolved + if (conflicts.find(c => c.locId === uniqueConflictId)) return; + if (resolvedConflicts.includes(uniqueConflictId)) return; + + conflicts.push({ + locId: uniqueConflictId, + realLocId: locId, + locationName: locDef?.name || locId, + playerActor, + opponents: sameTypeOpponents.map(o => ({ + ...o, + name: PLAYERS.find(p => p.id === o.playerId)?.name || 'Unknown', + playerAvatar: PLAYERS.find(p => p.id === o.playerId)?.avatar || '', + })), + resourceType: locDef?.resource || 'glory' + }); + } + }); + } + }); + return conflicts; + }, [phase, placedActors, disabledLocations, resolvedConflicts]); + + // Derived: Current Active Conflict Object + const currentConflict = useMemo(() => { + return activeConflicts.find(c => c.locId === activeConflictLocId); + }, [activeConflicts, activeConflictLocId]); + + const handleConflictResolve = (result: ConflictResult) => { + if (!activeConflictLocId) return; + + addLog(`Conflict at ${activeConflictLocId} complete.`); + result.logs.forEach(l => addLog(`> ${l}`)); + + if (result.restart) { + // Logic to restart: Close modal so user can click sidebar again + addLog("Conflict is restarting due to Lose Bid..."); + setActiveConflictLocId(null); + return; + } + + // Logic for Reward + if (result.winnerId === 'p1') { + const locDef = LOCATIONS.find(l => l.id === activeConflictLocId); + if (locDef) { + // Double prize check inside result logs? Or logic here? + // Modal logic pushed "Product Bid! DOUBLE PRIZE!" log. + // We should check the player's bid to trust the state. + const actor = placedActors.find(a => a.actorId === currentConflict?.playerActor.actorId); + const isDouble = actor?.bid === 'product'; + const baseReward = 1; + const finalReward = isDouble ? 2 : baseReward; + + updateResource(locDef.resource, (resources as any)[locDef.resource] + finalReward); + addLog(`You won ${finalReward} ${locDef.resource.toUpperCase()}!`); + } + } + + // Mark as resolved + setResolvedConflicts(prev => [...prev, activeConflictLocId]); + setActiveConflictLocId(null); + }; + // --- Derived State --- const usedRSPs = placedActors.filter(p => p.playerId === "p1").map(p => p.type); @@ -138,6 +375,9 @@ export default function GameBoardPage() { // Hydration matching for random event const randomEvent = EVENTS[Math.floor(Math.random() * EVENTS.length)]; setCurrentEvent(randomEvent); + + // DEBUG: Hand is empty at start + setActionHand([]); }, []); @@ -172,6 +412,7 @@ export default function GameBoardPage() { if (win && currentEvent.reward === "glory") updateResource('glory', resources.glory + 1); setEventResult({ msg, win }); + addLog(`Event Result: ${msg}`); }; const closeEvent = () => { @@ -186,15 +427,67 @@ export default function GameBoardPage() { setPendingPlacement(null); }; - const handleHexClick = (locId: string) => { + // Generic Card Action Handler + const handleCardAction = (cardId: string, locId: string) => { + // Implement "Stopping Locations" logic (Phase 3 Step 2) + if (p3Step === 2) { + setDisabledLocations(prev => [...prev, locId]); + addLog(`${player.name || '080'} disabled ${locId}`); + // Decrement card... (Assuming unlimited for now or need similar logic to teleport) + + // Simple card consumption from hand simulation + const cardIndex = actionHand.findIndex(c => c.type === 'location'); // roughly + if (cardIndex !== -1) { + setActionHand(prev => { + const newHand = [...prev]; + newHand.splice(cardIndex, 1); + return newHand; + }); + } + } + } + + const handleHexClick = async (locId: string) => { if (disabledLocations.includes(locId)) return; // Teleport overrides - if (phase === 3 && activeCardId === 'teleport' && teleportSource) { - setPlacedActors(prev => prev.map(p => p.actorId === teleportSource ? { ...p, locId } : p)); - setActivatedCards(prev => [...prev, 'teleport']); + // Phase 3 Step 2: Stopping Locations + if (phase === 3 && p3Step === 2 && activeCardId) { + handleCardAction(activeCardId, locId); setActiveCardId(null); + return; + } + + // Phase 3 Step 3: Teleportation + if (phase === 3 && p3Step === 3 && teleportSource) { + const actor = placedActors.find(p => p.actorId === teleportSource); + if (!actor) return; + + // Validate Move - Robot Requirement or general proximity if needed + // For now, if robot, we can strictly enforce ALLOWED_MOVES again as a "hint" + if (actor.type === 'robot') { + const validTargets = ALLOWED_MOVES[actor.type]; + if (!validTargets?.includes(locId)) { + addLog(`Invalid move for Robot! Must move to ${validTargets?.join(', ')}`); + return; + } + } + + // Execute Teleport + setPlacedActors(prev => prev.map(p => p.actorId === teleportSource ? { ...p, locId } : p)); setTeleportSource(null); + + // Consume Card + const cardIndex = actionHand.findIndex(c => c.id.includes('relocation') || c.id.includes('teleport')); + if (cardIndex !== -1) { + setActionHand(prev => { + const newHand = [...prev]; + newHand.splice(cardIndex, 1); + return newHand; + }); + } + + await addLog(`${player.name || '080'} teleported ${actor.type} to ${locId}`); return; } @@ -220,15 +513,65 @@ export default function GameBoardPage() { const handleRSPSelect = (type: string) => { if (pendingPlacement) { + const actor = MY_ACTORS.find(a => a.id === pendingPlacement.actorId); setPlacedActors(prev => [ ...prev, - { actorId: pendingPlacement.actorId, playerId: "p1", locId: pendingPlacement.locId, type, isOpponent: false } + { + actorId: pendingPlacement.actorId, + playerId: "p1", + locId: pendingPlacement.locId, + type, + isOpponent: false, + actorType: actor?.type || 'unknown' // Add actorType for conflict matching + } ]); setPendingPlacement(null); setSelectedActorId(null); - // Auto-advance if all placed? Logic for now: user manually clicks Done or we check length + addLog(`${player.name || '080'} placed ${actor?.name} with ${type.toUpperCase()} to ${pendingPlacement.locId}`); + } + }; + + const handleBid = (resourceType: 'product' | 'energy' | 'recycle' | null) => { + if (!biddingActorId) return; + + const actorEntry = placedActors.find(p => p.actorId === biddingActorId); + const oldBid = actorEntry?.bid as 'product' | 'energy' | 'recycle' | undefined; + + // 1. Clear/Detach Logic: If resourceType is null OR same as oldBid + if (resourceType === null || oldBid === resourceType) { + if (oldBid) { + updateResource(oldBid, (resources[oldBid] || 0) + 1); + setPlacedActors(prev => prev.map(p => + p.actorId === biddingActorId ? { ...p, bid: undefined } : p + )); + addLog(`${player.name || '080'} removed bet from actor`); + } + setBiddingActorId(null); + return; + } + + // 2. Check if new resource is available + const newAmount = (resources as any)[resourceType] || 0; + if (newAmount <= 0) return; + + // 3. Swap Logic: Return old resource if it exists + if (oldBid) { + updateResource(oldBid, (resources[oldBid] || 0) + 1); } + + // 4. Deduct new resource + updateResource(resourceType, newAmount - 1); + + // 5. Update placed actor + setPlacedActors(prev => prev.map(p => + p.actorId === biddingActorId ? { ...p, bid: resourceType } : p + )); + + const actor = MY_ACTORS.find(a => a.id === biddingActorId); + const betType = resourceType === 'product' ? 'WIN' : resourceType === 'energy' ? 'LOSE' : 'DRAW'; + addLog(`${player.name || '080'} BET ON ${betType} with ${actor?.name}`); + setBiddingActorId(null); }; const handleActorRecall = (actor: any) => { @@ -236,6 +579,7 @@ export default function GameBoardPage() { if (actor.playerId !== 'p1') return; console.log("Recalling actor:", actor.actorId); + addLog(`Recalled ${actor.type} from map`); setPlacedActors(prev => prev.filter(p => p.actorId !== actor.actorId)); // Reset any pending states to prevent UI ghosting @@ -243,6 +587,53 @@ export default function GameBoardPage() { setPendingPlacement(null); }; + // Phase 3 Step 4: Exchange Logic + const handleExchangeConfirm = (give: 'power' | 'art' | 'wisdom', take: 'power' | 'art' | 'wisdom') => { + if (!exchangeTarget) return; + + const opponentId = exchangeTarget.id; + const opponentName = exchangeTarget.name; + + // Functional updates for safety + setOpponentsData(prev => { + const next = { ...prev }; + if (!next[opponentId]) return prev; + + const oppRes = { ...next[opponentId].resources }; + + // Adjust opponent resources + const giveKey = give === 'wisdom' ? 'knowledge' : give; + const takeKey = take === 'wisdom' ? 'knowledge' : take; + + oppRes[giveKey] = (oppRes[giveKey] || 0) + 1; + oppRes[takeKey] = Math.max(0, (oppRes[takeKey] || 0) - 1); + + next[opponentId] = { ...next[opponentId], resources: oppRes }; + return next; + }); + + // Update player resources + const playerGiveKey = give === 'wisdom' ? 'knowledge' : give; + const playerTakeKey = take === 'wisdom' ? 'knowledge' : take; + + updateResource(playerGiveKey, (resources as any)[playerGiveKey] - 1); + updateResource(playerTakeKey, (resources as any)[playerTakeKey] + 1); + + addLog(`${player.name || '080'} exchanged ${give.toUpperCase()} for ${take.toUpperCase()} with ${opponentName}`); + + // Consume Card + const cardIndex = actionHand.findIndex(c => c.id.includes('change_values') || c.id.includes('exchange')); + if (cardIndex !== -1) { + setActionHand(prev => { + const newHand = [...prev]; + newHand.splice(cardIndex, 1); + return newHand; + }); + } + + setExchangeTarget(null); + }; + // --- Phase Advancement --- const handleNextPhase = () => { if (turn === 7 && phase === 5) { @@ -250,11 +641,29 @@ export default function GameBoardPage() { return; } + // Phase 3 Sub-step Logic + if (phase === 3) { + if (p3Step < 4) { + const nextStep = (p3Step + 1) as 1 | 2 | 3 | 4; + setP3Step(nextStep); + const stepNames = ["", "BIDDING", "STOPPING LOCATIONS", "RELOCATION", "EXCHANGE"]; + addLog(`${player.name || '080'} advanced to ${stepNames[nextStep]}`); + return; + } + } + if (phase < 5) { - setPhase(phase + 1); + const nextPhase = phase + 1; + setPhase(nextPhase); + // Reset P3 step when leaving P3 + if (nextPhase !== 3) setP3Step(1); + addLog(`${player.name || '080'} ready`); + addLog(`PHASE ${nextPhase}`); } else { setPhase(1); + setP3Step(1); setTurn(t => t + 1); + addLog(`TURN ${turn + 1} BEGINS`); } }; @@ -267,6 +676,7 @@ export default function GameBoardPage() { {/* 1. Map Layer (Background / Center) */} { - handleActorRecall(actor); + if (phase === 2) handleActorRecall(actor); + if (phase === 3 && p3Step === 1 && actor.playerId === 'p1') { + // Toggle menu + setBiddingActorId(prev => prev === actor.actorId ? null : actor.actorId); + } + if (phase === 3 && p3Step === 3 && actor.playerId === 'p1') { + // Start Teleport if cards available + if (teleportCardsCount > 0) { + setTeleportSource(prev => prev === actor.actorId ? null : actor.actorId); + if (teleportSource !== actor.actorId) { + addLog(`Selected ${actor.type} for teleport... choose a destination.`); + } + } else { + addLog("No Relocation cards available."); + } + } }} /> {/* 2. UI Overlay Layer (Z-Indexed) */} -
+
{/* Top Center: Header (Snapped) */} + {/* Phase 4: Conflicts Sidebar */} + {phase === 4 && ( + !resolvedConflicts.includes(c.locId))} + activeConflictLocId={activeConflictLocId} + onSelectConflict={setActiveConflictLocId} + /> + )} + + {/* Phase 4: Conflict Resolution Modal */} + {phase === 4 && activeConflictLocId && currentConflict && ( +
+ setActiveConflictLocId(null)} + /> +
+ )} + {/* Top Center: Resources (Layered ABOVE Header) */} {/* Top Left: New Players Panel (SVG) */} - + setExchangeTarget({ id, name, x: 0, y: 0 })} // x/y not needed for modal + /> {/* Left Sidebar: Actors / Hand */}
@@ -312,8 +767,20 @@ export default function GameBoardPage() { onLeave={() => setHoveredActorId(null)} /> )} + {phase === 3 && p3Step > 1 && ( + = 3} + /> + )}
+ + + {/* Bottom Right: Next Phase Button */} {/* Bottom Right: Next Phase Button */} {/* Bottom Right: Next Phase Button */}
@@ -321,9 +788,14 @@ export default function GameBoardPage() { {(phase !== 2 || availableActors.length === 0) && ( )}
@@ -340,39 +812,104 @@ export default function GameBoardPage() {
)} - {/* --- Phase 1: Event Modal --- */} - {phase === 1 && ( -
-
-

{currentEvent.title}

-
- event -
-

"{currentEvent.flavor}"

-

{currentEvent.desc}

- - {!eventResult ? ( -
- {currentEvent.type === "discard" && ( -
- - {discardAmount} - + {/* --- Bidding Menu for Phase 3 --- */} + {phase === 3 && biddingActorId && ( +
+
+

Make a Bid...

+
+ {[ + { type: 'product', label: 'bet on win', icon: '/resources/resource_box.png', color: 'bg-red-500/10' }, + { type: 'energy', label: 'bet on lose', icon: '/resources/resource_energy.png', color: 'bg-blue-500/10' }, + { type: 'recycle', label: 'bet on draw', icon: '/resources/resource_bio.png', color: 'bg-green-500/10' } + ].map((res) => ( + -
- ) : ( -
-

{eventResult.msg}

- -
- )} + {res.label} + {resources[res.type as keyof typeof resources]} + + ))} +
+
+ + +
+
+ ) + } + + {/* --- Exchange Modal --- */} + {exchangeTarget && ( +
+ setExchangeTarget(null)} + onConfirm={handleExchangeConfirm} + targetName={exchangeTarget.name} + playerResources={resources} + opponentResources={opponentsData[exchangeTarget.id]?.resources || {}} + />
)} -
- - + + {/* --- Phase 1: Event Modal --- */} + { + phase === 1 && ( +
+
+

{currentEvent.title}

+
+ event +
+

"{currentEvent.flavor}"

+

{currentEvent.desc}

+ + {!eventResult ? ( +
+ {currentEvent.type === "discard" && ( +
+ + {discardAmount} + +
+ )} + +
+ ) : ( +
+

{eventResult.msg}

+ +
+ )} +
+
+ ) + } +
+ + ); } diff --git a/frontend/app/game/create/page.tsx b/frontend/app/game/create/page.tsx index 58e6f18..d23d967 100644 --- a/frontend/app/game/create/page.tsx +++ b/frontend/app/game/create/page.tsx @@ -3,7 +3,7 @@ import ProfileWidget from "@/components/ProfileWidget"; import MetarchyButton from "@/components/MetarchyButton"; import Link from "next/link"; -import { Copy, ChevronDown, Check, User, Loader2 } from "lucide-react"; +import { Copy, ChevronDown, Check, User, Loader2, RefreshCw } from "lucide-react"; import Image from "next/image"; import { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; @@ -11,9 +11,25 @@ import { useGameState } from "@/context/GameStateContext"; import citizens from "@/data/citizens.json"; import { v4 as uuidv4 } from 'uuid'; +const FUTURISTIC_ADJECTIVES = [ + "Neon", "Cyber", "Neural", "Quantum", "Void", "Zenith", "Plasma", "Aura", "Nova", "Vector", + "Synth", "Orbital", "Hyper", "Solar", "Logic", "Meta", "Prism", "Glitch", "Echo", "Core" +]; + +const FUTURISTIC_NOUNS = [ + "Nexus", "Spire", "Vortex", "Matrix", "Vault", "Harbor", "Gate", "Pulse", "Shell", "Bridge", + "Grid", "Node", "Station", "Bastion", "Summit", "Point", "Link", "Zone", "Flow", "Drift" +]; + +const getRandomRoomName = () => { + const adj = FUTURISTIC_ADJECTIVES[Math.floor(Math.random() * FUTURISTIC_ADJECTIVES.length)]; + const noun = FUTURISTIC_NOUNS[Math.floor(Math.random() * FUTURISTIC_NOUNS.length)]; + return `${adj}_${noun}`; +}; + export default function CreateGamePage() { const { player, lobby, createRoom, joinRoom } = useGameState(); - const [roomName, setRoomName] = useState("Metarchy_Genesis"); + const [roomName, setRoomName] = useState(""); const [playerCount, setPlayerCount] = useState(3); const [isCreating, setIsCreating] = useState(false); const [isPrivate, setIsPrivate] = useState(false); @@ -21,9 +37,10 @@ export default function CreateGamePage() { const [preGeneratedId, setPreGeneratedId] = useState(""); const router = useRouter(); - // Initialize pre-generated ID on mount + // Initialize pre-generated ID and random Room Name on mount useEffect(() => { setPreGeneratedId(uuidv4()); + setRoomName(getRandomRoomName()); }, []); const handleCreate = async () => { @@ -90,14 +107,22 @@ export default function CreateGamePage() {
-
+
setRoomName(e.target.value)} disabled={isCreating} - className="w-full bg-black/50 border border-white/10 rounded px-4 py-3 text-white focus:outline-none focus:border-[#d4af37] transition-colors disabled:opacity-50" + className="w-full bg-black/50 border border-white/10 rounded px-4 py-3 pr-12 text-white focus:outline-none focus:border-[#d4af37] transition-colors disabled:opacity-50" /> +
diff --git a/frontend/app/game/lobby/[id]/page.tsx b/frontend/app/game/lobby/[id]/page.tsx index f0e2016..01f20bc 100644 --- a/frontend/app/game/lobby/[id]/page.tsx +++ b/frontend/app/game/lobby/[id]/page.tsx @@ -41,13 +41,8 @@ export default function LobbyPage() { setMessages(data.messages || []); // Handle Start Trigger - if (data.status === 'starting' && data.startTime) { - const timeLeft = Math.floor((data.startTime - Date.now()) / 1000); - if (timeLeft <= 0) { - router.push(`/game/board/${id}`); - } else { - setCountdown(timeLeft); - } + if (data.status === 'playing') { + router.push(`/game/board/${id}`); } else if (data.status === 'waiting') { setCountdown(null); } diff --git a/frontend/components/OnboardingModal.tsx b/frontend/components/OnboardingModal.tsx index 63f5329..fa5c57b 100644 --- a/frontend/components/OnboardingModal.tsx +++ b/frontend/components/OnboardingModal.tsx @@ -1,5 +1,11 @@ "use client"; +declare global { + interface Window { + ethereum?: any; + } +} + import React, { useState } from 'react'; import { useGameState } from '../context/GameStateContext'; import { useRouter } from 'next/navigation'; @@ -11,7 +17,7 @@ import { WindowFrame } from './WindowFrame'; import { CompactFrame } from './CompactFrame'; export default function OnboardingModal({ isOpen, onClose }: { isOpen: boolean, onClose: () => void }) { - const { setPlayerName, setPlayerAddress, setCitizenId, setPlayer } = useGameState(); + const { player, setPlayerName, setPlayerAddress, setCitizenId, setPlayer } = useGameState(); const router = useRouter(); const [step, setStep] = useState<'connect' | 'create' | 'minting' | 'success'>('connect'); const [name, setName] = useState(''); @@ -22,72 +28,92 @@ export default function OnboardingModal({ isOpen, onClose }: { isOpen: boolean, // if (!isOpen) return null; const handleConnect = async () => { + if (!window.ethereum) { + setError("MetaMask not detected. Please install the extension."); + return; + } + setIsLoading(true); setError(null); - console.log("Initiating connection..."); - - // Mock connection (replace with valid wallet login logic as needed) - // In a real app, we'd get the address from the wallet provider - // For now, we simulate a connection - const mockAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; // Fixed for demo, or random if desired + console.log("Initiating real wallet connection..."); - // Simulate delay - await new Promise(resolve => setTimeout(resolve, 600)); + try { + // Request accounts from MetaMask + const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); + if (!accounts || accounts.length === 0) { + setError("No accounts found. Please unlock MetaMask."); + setIsLoading(false); + return; + } - // setPlayerAddress(mockAddress); + const connectedAddress = accounts[0]; + console.log("Connected address:", connectedAddress); + setPlayerAddress(connectedAddress); - // Check user registration - try { - console.log("Fetching citizen data for:", mockAddress); - const res = await fetch(`/api/citizen?address=${mockAddress}`); - console.log("API Response status:", res.status); + // Check user registration + console.log("Fetching citizen data for:", connectedAddress); + const res = await fetch(`/api/citizen?address=${connectedAddress}`); if (res.ok) { const data = await res.json(); - console.log("User found:", data); - // User exists! + console.log("Citizen found:", data); + + // Update status to online + await fetch('/api/citizen', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ address: connectedAddress, status: 'online' }) + }); + setPlayer({ - address: mockAddress, + address: connectedAddress, name: data.name, citizenId: data.citizenId, - avatar: data.avatar || "/avatars/golden_avatar.png" // Fallback to default + avatar: data.avatar || "/avatars/golden_avatar.png" }); setGeneratedId(data.citizenId); - setName(data.name); // Pre-fill name state for success screen + setName(data.name); setStep('success'); } else { - console.log("User not found, proceeding to creation."); - setPlayerAddress(mockAddress); - // User is new + console.log("Citizen not found, proceeding to creation."); setStep('create'); } - } catch (e) { - console.error("Failed to check registration:", e); - setError("Connection failed. Please try again."); - // setStep('create'); // Don't auto-advance on error, let user see it + } catch (e: any) { + console.error("Wallet connection failed:", e); + if (e.code === 4001) { + setError("Connection request rejected by user."); + } else { + setError("Failed to connect wallet. Please try again."); + } } finally { setIsLoading(false); } }; const handleCreate = async () => { - if (!name) return; + if (!name || !player.address) return; setStep('minting'); - const currentAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; // Matching handleConnect - try { const res = await fetch('/api/citizen', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ address: currentAddress, name: name }) + body: JSON.stringify({ address: player.address, name: name }) }); if (res.ok) { const data = await res.json(); + + // Update status to online (Identity just minted) + await fetch('/api/citizen', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ address: player.address, status: 'online' }) + }); + setGeneratedId(data.citizenId); setPlayer({ - address: currentAddress, + address: player.address, name: data.name, citizenId: data.citizenId, avatar: data.avatar || "/avatars/golden_avatar.png" diff --git a/frontend/components/ProfileWidget.tsx b/frontend/components/ProfileWidget.tsx index a5a92ce..b344eca 100644 --- a/frontend/components/ProfileWidget.tsx +++ b/frontend/components/ProfileWidget.tsx @@ -2,10 +2,35 @@ import React from 'react'; import { useGameState } from '../context/GameStateContext'; export default function ProfileWidget() { - const { player } = useGameState(); + const { player, setPlayer } = useGameState(); if (!player || !player.citizenId || player.citizenId === "0000") return null; + const handleLogout = async () => { + if (!player.address) return; + + try { + await fetch('/api/citizen', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ address: player.address, status: 'offline' }) + }); + + // Clear local state + setPlayer({ + name: "", + address: "", + citizenId: "0000", + avatar: "" + }); + + // Redirect or refresh + window.location.href = '/'; + } catch (e) { + console.error("Logout failed:", e); + } + }; + return (
{/* @@ -96,15 +121,15 @@ export default function ProfileWidget() { )}
- {/* 4. Profile Menu Button */} - {/* Positioned 5px from top-right page corner (local coords to snapped container) */} + {/* 4. Profile Menu Button / Logout */} +
+ )} + + {/* MODAL: Outcome & Interaction */} + + {(step === 'outcome_rsp' || step === 'outcome_bid') && ( +
+ + {/* Header */} +
+

+ {result?.isDraw ? 'DRAW' : result?.winnerId === 'p1' ? 'VICTORY' : 'DEFEAT'} +

+

+ {result?.isDraw + ? "The negotiation stalled. Arguments were inconclusive." + : result?.winnerId === 'p1' + ? "Your arguments prevailed over the opposition." + : "You failed to convince the assembly." + } +

+
+ + {/* Body */} +
+ + {/* DRAW: Re-Selection */} + {step === 'outcome_rsp' && result?.isDraw && ( +
+

Resolve the dispute. Choose argument:

+
+ {['rock', 'paper', 'scissors'].map(token => ( + + ))} +
+
+ )} + + {/* WIN/LOSE: Next/Close */} + {step === 'outcome_rsp' && !result?.isDraw && ( +
+
+ Status +
+

Conflict Resolved

+ +
+ )} + + {/* BID OUTCOME STAGE */} + {step === 'outcome_bid' && ( +
+
+

BID EFFECT TRIGGERED

+
    + {result?.logs.map((log, i) => ( +
  • + + {log} +
  • + ))} +
+
+ +
+ )} + +
+
+
+ )} +
+ +
+ ); +} + diff --git a/frontend/components/game/ConflictsSidebar.tsx b/frontend/components/game/ConflictsSidebar.tsx new file mode 100644 index 0000000..8fce971 --- /dev/null +++ b/frontend/components/game/ConflictsSidebar.tsx @@ -0,0 +1,100 @@ +"use client"; + +import React from 'react'; +import { Swords } from 'lucide-react'; +import { motion } from 'framer-motion'; +import ActorOrb from './ActorOrb'; +import OtherPlayerActorMarker from './OtherPlayerActorMarker'; + +interface Conflict { + locId: string; + locationName: string; + playerActor: any; + opponents: any[]; +} + +interface ConflictsSidebarProps { + conflicts: Conflict[]; + activeConflictLocId: string | null; + onSelectConflict: (locId: string) => void; +} + +export default function ConflictsSidebar({ conflicts, activeConflictLocId, onSelectConflict }: ConflictsSidebarProps) { + if (conflicts.length === 0) return null; + + return ( + +
+ +

Active Conflicts

+
+ +
+ {conflicts.map((conflict) => { + const isActive = activeConflictLocId === conflict.locId; + return ( + + ); + })} +
+
+ ); +} diff --git a/frontend/components/game/ExchangeModal.tsx b/frontend/components/game/ExchangeModal.tsx new file mode 100644 index 0000000..c0d7495 --- /dev/null +++ b/frontend/components/game/ExchangeModal.tsx @@ -0,0 +1,175 @@ +"use client"; + +import React, { useState } from 'react'; +import { X, ArrowRightLeft } from 'lucide-react'; +import Image from 'next/image'; + +interface ExchangeModalProps { + isOpen: boolean; + onClose: () => void; + onConfirm: (give: 'power' | 'art' | 'wisdom', take: 'power' | 'art' | 'wisdom') => void; + targetName: string; + playerResources: Record; + opponentResources: Record; +} + +const RESOURCES = [ + { id: 'power', label: 'Power', icon: '/intangibles/resource_power.png' }, + { id: 'art', label: 'Art', icon: '/intangibles/resource_Art.png' }, + { id: 'wisdom', label: 'Wisdom', icon: '/intangibles/resource_wisdom.png' } +] as const; + +type ResourceId = 'power' | 'art' | 'wisdom'; + +export default function ExchangeModal({ + isOpen, + onClose, + onConfirm, + targetName, + playerResources, + opponentResources +}: ExchangeModalProps) { + const [give, setGive] = useState(null); + const [take, setTake] = useState(null); + + if (!isOpen) return null; + + return ( +
+
+ {/* Header */} +
+
+
+ +
+

Resource Exchange

+
+ +
+ + {/* Content */} +
+

+ Select a resource to give and a resource to take from {targetName}. +

+ +
+ {/* Give Section */} +
+

You Give

+
+ {RESOURCES.map((res) => { + const resourceKey = res.id === 'wisdom' ? 'knowledge' : res.id; + const count = playerResources[resourceKey] || 0; + const isDisabled = count <= 0; + + return ( + + ); + })} +
+
+ + {/* Divider Icon */} +
+
+ +
+
+ + {/* Take Section */} +
+

{targetName} Gives You

+
+ {RESOURCES.map((res) => { + const resourceKey = res.id === 'wisdom' ? 'knowledge' : res.id; + const count = opponentResources[resourceKey] || 0; + const isDisabled = count <= 0; + + return ( + + ); + })} +
+
+
+ + {/* Actions */} +
+ + +
+
+
+
+ ); +} diff --git a/frontend/components/game/GameLog.tsx b/frontend/components/game/GameLog.tsx new file mode 100644 index 0000000..e2a92da --- /dev/null +++ b/frontend/components/game/GameLog.tsx @@ -0,0 +1,49 @@ +"use client"; + +import React, { useEffect, useRef } from 'react'; +import { ScrollText } from 'lucide-react'; + +interface GameLogProps { + logs: string[]; +} + +export default function GameLog({ logs }: GameLogProps) { + const scrollRef = useRef(null); + + useEffect(() => { + if (scrollRef.current) { + scrollRef.current.scrollTop = scrollRef.current.scrollHeight; + } + }, [logs]); + + return ( +
+
+ + Command Log +
+ +
+ {logs.length === 0 ? ( +
Waiting for uplink...
+ ) : ( + logs.map((log, i) => ( +
+ + [{new Date().toLocaleTimeString([], { hour12: false, hour: '2-digit', minute: '2-digit' })}] + +

+ {log} +

+
+ )) + )} +
+ +
+
+ ); +} diff --git a/frontend/components/game/GameResources.tsx b/frontend/components/game/GameResources.tsx index 2cc3823..07c74fb 100644 --- a/frontend/components/game/GameResources.tsx +++ b/frontend/components/game/GameResources.tsx @@ -70,28 +70,28 @@ export default function GameResources({ resources, vp }: GameResourcesProps) { {/* Resource Slots - Positioned based on user provided coords */} {/* VP (White) x=35.15 y=3.5 - NOW STAR/FAME */} - {renderSlot(35.15, 3.5, "/intangibles/resource_fame.png", vp, "VP")} + {renderSlot(35.15, 3.5, "/intangibles/resource_VP.png", vp, "VP")} {/* Glory (Yellow) x=118.15 y=3.5 - NOW VICTORY */} - {renderSlot(118.15, 3.5, "/intangibles/resource_victory.png", resources.glory, "Glory")} + {renderSlot(118.15, 3.5, "/intangibles/resource_Glory.png", resources.glory, "Glory")} {/* Power (Orange) x=189.15 y=4.5 */} - {renderSlot(189.15, 4.5, "/intangibles/resource_ledger.png", resources.power, "Power")} + {renderSlot(189.15, 4.5, "/intangibles/resource_power.png", resources.power, "Power")} {/* Art (Magenta) x=260.15 y=4.5 */} - {renderSlot(260.15, 4.5, "/intangibles/resource_culture.png", resources.art, "Art")} + {renderSlot(260.15, 4.5, "/intangibles/resource_Art.png", resources.art, "Art")} {/* Wisdom (Light Blue) x=331.15 y=4.5 */} - {renderSlot(331.15, 4.5, "/intangibles/resource_focus.png", resources.knowledge, "Wisdom")} + {renderSlot(331.15, 4.5, "/intangibles/resource_wisdom.png", resources.knowledge, "Wisdom")} {/* Product (Red) x=404.15 y=3.5 */} - {renderSlot(404.15, 3.5, "/resources/resource_box.png", resources.product, "Product")} + {renderSlot(404.15, 3.5, "/resources/resource_product.png", resources.product, "Product")} {/* Energy (Blue) x=475.15 y=3.5 */} {renderSlot(475.15, 3.5, "/resources/resource_energy.png", resources.energy, "Energy")} {/* Recycle (Green) x=545.15 y=3.5 */} - {renderSlot(545.15, 3.5, "/resources/resource_bio.png", resources.recycle, "Recycle")} + {renderSlot(545.15, 3.5, "/resources/resource_Recycle.png", resources.recycle, "Recycle")}
diff --git a/frontend/components/game/MapContainer.tsx b/frontend/components/game/MapContainer.tsx index 739dce2..1f16343 100644 --- a/frontend/components/game/MapContainer.tsx +++ b/frontend/components/game/MapContainer.tsx @@ -11,6 +11,7 @@ const CITIZENS = citizensData as any[]; // Type assertion for simple usage interface MapContainerProps { phase: number; + p3Step?: number; placedActors: any[]; selectedActorId: string | null; hoveredActorId: string | null; @@ -19,6 +20,7 @@ interface MapContainerProps { selectedHex: string | null; playerActorsV2: any[]; players: any[]; + availableTeleportCards?: number; onHexClick: (locId: string) => void; onPlayerClick: (actor: any, event: React.MouseEvent) => void; } @@ -34,6 +36,7 @@ const ACTOR_AVATARS: { [key: string]: string } = { export default function MapContainer({ phase, + p3Step, placedActors, selectedActorId, hoveredActorId, @@ -42,40 +45,72 @@ export default function MapContainer({ selectedHex, playerActorsV2, players, + availableTeleportCards, onHexClick, onPlayerClick }: MapContainerProps) { const [scale, setScale] = useState(0.7); + const [offset, setOffset] = useState({ x: 0, y: 0 }); + const [isDragging, setIsDragging] = useState(false); + const [dragStart, setDragStart] = useState({ x: 0, y: 0 }); const [hoveredLocId, setHoveredLocId] = useState(null); + // Zoom Compensation logic: keep HUD size constant as seen in Phase 2 + const BASE_ZOOM = 0.7; + const currentZoomFactor = phase >= 3 ? 1.6 : 0.7; + const hudScale = BASE_ZOOM / currentZoomFactor; + useEffect(() => { if (typeof window !== 'undefined') { const updateScale = () => { const baseScale = Math.min(window.innerWidth / 1920, window.innerHeight / 1080); - const zoomFactor = phase >= 3 ? 0.9 : 0.7; - setScale(baseScale * zoomFactor); + setScale(baseScale * currentZoomFactor); }; updateScale(); window.addEventListener('resize', updateScale); return () => window.removeEventListener('resize', updateScale); } - }, [phase]); + }, [phase, currentZoomFactor]); + + const handleMouseDown = (e: React.MouseEvent) => { + if (e.button !== 0) return; // Only left click + setIsDragging(true); + setDragStart({ x: e.clientX - offset.x, y: e.clientY - offset.y }); + }; + + const handleMouseMove = (e: React.MouseEvent) => { + if (!isDragging) return; + setOffset({ + x: e.clientX - dragStart.x, + y: e.clientY - dragStart.y + }); + }; - const activeActorId = hoveredActorId || selectedActorId; + const handleMouseUp = () => { + setIsDragging(false); + }; + + const activeActorId = teleportSource || hoveredActorId || selectedActorId; const activeActor = activeActorId ? playerActorsV2.find(a => a.id === activeActorId) : null; const validLocs = activeActor ? ALLOWED_MOVES[activeActor.type] || [] : []; return ( -
+
{/* Background Map Layer */}
= 4 ? 'blur-sm brightness-50' : ''}`} />
{/* Virtual Canvas for Fixed 1080p Positioning */}
{LOCATIONS.map(loc => { @@ -172,26 +207,38 @@ export default function MapContainer({ if (!isVisible) return null; // Resolve full actor details - const actorDetails = playerActorsV2.find(origin => origin.id === a.actorId) || a; + const actorDetails = playerActorsV2.find(origin => origin.id === a.actorId) || { ...a, type: a.actorType || a.type }; const token = a.type !== actorDetails.type ? a.type : undefined; + // Centered Spread Logic + const spread = 100; + const startX = -((actorsHere.length - 1) * spread) / 2; + const currentX = startX + (i * spread); + const baseSlotY = phase >= 3 ? -4 : -34; + const opponentYOffset = a.playerId !== 'p1' ? -80 : 0; + const finalY = baseSlotY + opponentYOffset; + // Opponent Marker if (a.playerId !== 'p1') { - const pIndex = parseInt(a.playerId.replace('p', '')) - 1; - const playerAvatar = CITIZENS[pIndex]?.avatar || ""; + const opponent = players.find(p => p.id === a.playerId); + const playerAvatar = opponent?.avatar || ""; return (
= 4 ? a.bid : undefined} + hasSecretBid={phase === 3 && !!a.bid} phase={phase} + hudScale={hudScale} onClick={(e) => { e.stopPropagation(); onPlayerClick(a, e) }} />
@@ -202,17 +249,23 @@ export default function MapContainer({ return (
+ { e.stopPropagation(); onPlayerClick(a, e) }} />
diff --git a/frontend/components/game/NewPlayersPanel.tsx b/frontend/components/game/NewPlayersPanel.tsx index bacff30..19e7beb 100644 --- a/frontend/components/game/NewPlayersPanel.tsx +++ b/frontend/components/game/NewPlayersPanel.tsx @@ -3,17 +3,24 @@ import Image from 'next/image'; interface NewPlayersPanelProps { players?: any[]; + p3Step?: number; + availableExchangeCards?: number; + onExchangeClick?: (playerId: string, playerName: string) => void; } -export default function NewPlayersPanel({ players = [] }: NewPlayersPanelProps) { +export default function NewPlayersPanel({ players = [], p3Step, availableExchangeCards, onExchangeClick }: NewPlayersPanelProps) { // Data unpacking: p1 is Index 0 (User), p2/p3 are Index 1/2 (Opponents) const userPlayer = players[0] || { name: 'Citizen', avatar: '/avatars/golden_avatar.png' }; - const p2 = players[1] || { name: 'Viper', avatar: '/avatars/viper.png' }; - const p3 = players[2] || { name: 'Ghost', avatar: '/avatars/ghost.png' }; + const p2 = players[1] || { id: 'p2', name: 'Viper', avatar: '/avatars/viper.png' }; + const p3 = players[2] || { id: 'p3', name: 'Ghost', avatar: '/avatars/ghost.png' }; + + const showExchange = p3Step === 4 && availableExchangeCards && availableExchangeCards > 0; // Helper for circular avatar - const AvatarCircle = ({ x, y, r, img, alt, hasOuterRing }: { x: number, y: number, r: number, img: string, alt: string, hasOuterRing?: boolean }) => { + const AvatarCircle = ({ x, y, r, img, alt, player, hasOuterRing }: { x: number, y: number, r: number, img: string, alt: string, player?: any, hasOuterRing?: boolean }) => { const size = r * 2; + const isOpponent = !hasOuterRing && player; + return ( <> {hasOuterRing && ( @@ -39,15 +46,34 @@ export default function NewPlayersPanel({ players = [] }: NewPlayersPanelProps) )}
{ + if (isOpponent && showExchange && onExchangeClick) { + onExchangeClick(player.id, player.name); + } + }} > {alt} + + {/* Interaction Overlay */} + {isOpponent && showExchange && ( +
+ + + + + + +
+ )}
); @@ -63,7 +89,7 @@ export default function NewPlayersPanel({ players = [] }: NewPlayersPanelProps) {/* Gold Separator Line */} - + {/* Outline / Decor paths */} @@ -107,10 +133,14 @@ export default function NewPlayersPanel({ players = [] }: NewPlayersPanelProps)
{/* 4. Player 2 (Viper) */} - +
+ +
{/* 5. Player 3 (Ghost) */} - +
+ +
diff --git a/frontend/components/game/OtherPlayerActorMarker.tsx b/frontend/components/game/OtherPlayerActorMarker.tsx index ea824a1..bb39124 100644 --- a/frontend/components/game/OtherPlayerActorMarker.tsx +++ b/frontend/components/game/OtherPlayerActorMarker.tsx @@ -1,12 +1,14 @@ "use client"; -import React from 'react'; import Image from 'next/image'; interface OtherPlayerActorMarkerProps { - actor: { type: string, avatar: string, id: string }; // The actor (Magenta ring) - playerAvatar?: string; // The player's citizen avatar (Blue ring) + actor: { type: string, avatar: string, id: string }; // The actor + playerAvatar?: string; // The player's citizen avatar + bid?: string; // Attached resource type + hasSecretBid?: boolean; // New: indicates a bid exists but is hidden phase?: number; + hudScale?: number; onClick?: (e: React.MouseEvent) => void; } @@ -18,15 +20,51 @@ const FACE_Offsets: { [key: string]: string } = { 'robot': '50% 20%' }; -export default function OtherPlayerActorMarker({ actor, playerAvatar, phase, onClick }: OtherPlayerActorMarkerProps) { +const Resource_Icons: { [key: string]: string } = { + 'product': '/resources/resource_product.png', + 'energy': '/resources/resource_energy.png', + 'recycle': '/resources/resource_Recycle.png' +}; + +export default function OtherPlayerActorMarker({ actor, playerAvatar, bid, hasSecretBid, phase, hudScale = 1, onClick }: OtherPlayerActorMarkerProps) { const objectPosition = FACE_Offsets[actor.type.toLowerCase()] || '50% 20%'; - const baseScale = phase && phase >= 3 ? 'scale-[1.2]' : 'scale-100'; + const phaseScaleAdjust = phase && phase >= 3 ? 1.44 : 1.0; return (
+ {/* Bid Icon Overlay - Styled like GameResources panel */} + {(bid || hasSecretBid) && ( +
+ {/* Background Plate */} +
+ + {/* Icon */} +
+ {hasSecretBid ? ( +
+ ? +
+ ) : ( + {bid + )} +
+ + {!hasSecretBid && 1} +
+ )} {/* Layer 0: Background Fills */} @@ -89,12 +127,8 @@ export default function OtherPlayerActorMarker({ actor, playerAvatar, phase, onC - {/* Magenta Ring */} - - {/* Blue Ring */} -
); diff --git a/frontend/components/game/PlacedActorMarker.tsx b/frontend/components/game/PlacedActorMarker.tsx index af24488..2169fcf 100644 --- a/frontend/components/game/PlacedActorMarker.tsx +++ b/frontend/components/game/PlacedActorMarker.tsx @@ -1,14 +1,17 @@ "use client"; -import React from 'react'; import Image from 'next/image'; interface PlacedActorMarkerProps { actor: { type: string, avatar: string, id: string }; token?: string; // RSP token id + bid?: string; // Attached resource type isP1: boolean; isTeleporting?: boolean; phase?: number; + p3Step?: number; + availableTeleportCards?: number; + hudScale?: number; onClick?: (e: React.MouseEvent) => void; } @@ -19,15 +22,78 @@ const FACE_Offsets: { [key: string]: string } = { 'robot': '50% 20%' }; -export default function PlacedActorMarker({ actor, token, isP1, isTeleporting, phase, onClick }: PlacedActorMarkerProps) { +const Resource_Icons: { [key: string]: string } = { + 'product': '/resources/resource_box.png', + 'energy': '/resources/resource_energy.png', + 'recycle': '/resources/resource_bio.png' +}; + +export default function PlacedActorMarker({ actor, token, bid, isP1, isTeleporting, phase, p3Step, availableTeleportCards, hudScale = 1, onClick }: PlacedActorMarkerProps) { const objectPosition = FACE_Offsets[actor.type.toLowerCase()] || '50% 20%'; - const baseScale = phase && phase >= 3 ? 'scale-[1.4]' : 'scale-125'; + const phaseScaleAdjust = phase && phase >= 3 ? 1.5 : 1.25; + + const canTeleport = phase === 3 && p3Step === 3 && availableTeleportCards && availableTeleportCards > 0 && !isTeleporting; return (
+ {/* Phase 3 Interactions: Bidding & Teleport */} + {phase === 3 && ( +
+ {/* Bidding (Step 1 or View-Only) */} + {bid && ( +
{ + if (p3Step === 1) { + e.stopPropagation(); + onClick?.(e); + } + }} + > +
+
+ {bid} +
+ 1 +
+ )} + + {/* Step 1: Add Bid Button (if no bid) */} + {!bid && p3Step === 1 && ( + + )} + + {/* Step 3: Teleport Interaction (Only if cards available) */} + {p3Step === 3 && availableTeleportCards && availableTeleportCards > 0 && !isTeleporting && ( + + )} +
+ )} + {/* Layer 0: Background Fills */} diff --git a/frontend/data/citizens.json b/frontend/data/citizens.json index 76d6c87..8520e86 100644 --- a/frontend/data/citizens.json +++ b/frontend/data/citizens.json @@ -1,12 +1,4 @@ [ - { - "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "name": "080", - "citizenId": "3444", - "joinedAt": "2026-01-31T05:54:41.274Z", - "avatar": "/avatars/golden_avatar.png", - "role": "admin" - }, { "address": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "name": "Viper", @@ -20,5 +12,14 @@ "citizenId": "1002", "joinedAt": "2026-01-31T14:45:05.000Z", "avatar": "/avatars/ghost.png" + }, + { + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", + "name": "080", + "citizenId": "808546", + "joinedAt": "2026-02-01T16:21:33.104Z", + "avatar": "/avatars/golden_avatar.png", + "isOnline": true, + "lastActive": "2026-02-03T18:47:37.737Z" } ] \ No newline at end of file diff --git a/frontend/data/gameConstants.ts b/frontend/data/gameConstants.ts index 1fec88b..bcf00b9 100644 --- a/frontend/data/gameConstants.ts +++ b/frontend/data/gameConstants.ts @@ -88,11 +88,14 @@ export const LOCATIONS = [ ]; export const ACTION_CARDS = [ - { id: "teleport", title: "Teleportation", icon: "/events/event_ocean_platform.jpg", count: 1, type: "action", flavor: "Keep limbs inside.", desc: "Teleport to another location." }, - { id: "change", title: "Change Resource", icon: "/actions/action_card_exchange.png", count: 2, type: "action", flavor: "Forced exchange.", desc: "Swap intangible resources." }, - // Phase 3 Stops - { id: "student_strikes", title: "Student Strikes", icon: "/events/event_revolution.png", count: 0, type: "event", disables: "university", flavor: "No research today.", desc: "Disables University." }, - { id: "charity", title: "Charity Event", icon: "/actions/action_nonmat_priestess.png", count: 0, type: "event", disables: "theatre", flavor: "Private event.", desc: "Disables Theatre." }, + { id: "under_construction", title: "Under Construction", icon: "/actions/action_mat_red_monolith.png", type: "location", disables: "square", desc: "Disables The Square. No conflict or resources." }, + { id: "charity", title: "Charity Event", icon: "/actions/action_nonmat_priestess.png", type: "location", disables: "theatre", desc: "Disables The Theatre. No conflict or resources." }, + { id: "student_strikes", title: "Student Strikes", icon: "/events/event_revolution.png", type: "location", disables: "university", desc: "Disables University. No conflict or resources." }, + { id: "sabotage", title: "Sabotage", icon: "/actions/action_mat_cyber_spy.jpg", type: "location", disables: "factory", desc: "Disables Factory. No conflict or resources." }, + { id: "blackout", title: "Blackout", icon: "/events/event_ocean_platform.jpg", type: "location", disables: "energy", desc: "Disables Energy Station. No conflict or resources." }, + { id: "eco_protest", title: "Ecological Protest", icon: "/actions/action_mat_overgrowth.png", type: "location", disables: "dump", desc: "Disables Dump. No conflict or resources." }, + { id: "relocation", title: "Relocation", icon: "/actions/action_nonmat_sky_city.png", type: "action", desc: "Teleport an actor along with its RSP and bet." }, + { id: "change_values", title: "Change of Values", icon: "/actions/action_card_exchange.png", type: "action", desc: "Exchange an intangible resource with another player." }, ]; // Helper to check for conflicts diff --git a/frontend/data/games.json b/frontend/data/games.json index a2e8c09..09a625c 100644 --- a/frontend/data/games.json +++ b/frontend/data/games.json @@ -1,67 +1,612 @@ [ { - "id": "d8463916-f1bd-484c-ab4b-46fe50419786", - "roomId": "Metarchy_Genesis", + "id": "7bbcfd41-83c1-476b-a872-9aea5ee04804", + "roomId": "Nova_Drift", "status": "finished", - "createdAt": 1769944937182, + "isPrivate": false, + "createdAt": 1769964017575, "players": [ { - "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", "name": "080", - "citizenId": "3444", + "citizenId": "808546", "avatar": "/avatars/golden_avatar.png", - "joinedAt": 1769944937182 + "joinedAt": 1769964017575, + "isReady": true + }, + { + "name": "Ghost", + "citizenId": "1002", + "avatar": "/avatars/ghost.png", + "address": "0x3C44...93BC", + "joinedAt": 1769964019756, + "isReady": true + }, + { + "name": "Viper", + "citizenId": "1001", + "avatar": "/avatars/viper.png", + "address": "0x7099...79C8", + "joinedAt": 1769964024942, + "isReady": true } ], "maxPlayers": 3, "bidAmount": 0, "logs": [ - "Game created by 080" + "[001] [16:40:17 UTC] GAME CREATED BY 080", + "[001] [16:40:19 UTC] Ghost joined", + "[001] [16:40:24 UTC] Viper joined", + "[001] [16:40:48 UTC] Ghost (p3) ready", + "[001] [16:46:24 UTC] 080 placed a1 with PAPER to square", + "[001] [16:46:27 UTC] 080 placed a3 with SCISSORS to theatre", + "[001] [16:46:30 UTC] 080 placed a4 with ROCK to square", + "[001] [16:46:32 UTC] 080 placed a2 with DUMMY to factory" + ], + "transactions": [], + "messages": [ + { + "sender": "Ghost", + "avatar": "/avatars/ghost.png", + "content": "Hello world!", + "timestamp": 1769964021373 + }, + { + "sender": "Viper", + "avatar": "/avatars/viper.png", + "content": "Hello world!", + "timestamp": 1769964026478 + } ], - "transactions": [] + "startTime": 1769964038007, + "displayId": "001" }, { - "id": "4775d978-e127-4787-aea0-224a9b7ff78e", - "roomId": "Metarchy_Genesis", + "id": "7e0456fc-982c-4199-9820-76a4aacc2924", + "roomId": "Void_Bridge", "status": "finished", - "createdAt": 1769945342956, + "isPrivate": false, + "createdAt": 1769964639012, "players": [ { - "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", "name": "080", - "citizenId": "3444", + "citizenId": "808546", "avatar": "/avatars/golden_avatar.png", - "joinedAt": 1769945342956, + "joinedAt": 1769964639012, + "isReady": true + }, + { + "name": "Ghost", + "citizenId": "1002", + "avatar": "/avatars/ghost.png", + "address": "0x3C44...93BC", + "joinedAt": 1769964641099, + "isReady": true + }, + { + "name": "Viper", + "citizenId": "1001", + "avatar": "/avatars/viper.png", + "address": "0x7099...79C8", + "joinedAt": 1769964647992, "isReady": true } ], "maxPlayers": 3, "bidAmount": 0, "logs": [ - "Game created by 080" + "[002] [16:50:39 UTC] GAME CREATED BY 080", + "[002] [16:50:41 UTC] Ghost joined", + "[002] [16:50:47 UTC] Viper joined", + "[002] [16:51:02 UTC] Viper placed Politician with ROCK to square", + "[002] [16:51:03 UTC] Viper placed Robot with PAPER to factory", + "[002] [16:51:04 UTC] Viper placed Scientist with SCISSORS to university", + "[002] [16:51:05 UTC] Viper placed Artist with ROCK to theatre", + "[002] [16:51:06 UTC] Ghost placed Politician with SCISSORS to university", + "[002] [16:51:06 UTC] Ghost placed Robot with ROCK to dump", + "[002] [16:51:07 UTC] 080 placed Politician with ROCK to square", + "[002] [16:51:07 UTC] Ghost placed Scientist with PAPER to theatre", + "[002] [16:51:08 UTC] Ghost placed Artist with SCISSORS to square", + "[002] [16:51:08 UTC] Viper (p2) ready", + "[002] [16:51:10 UTC] Ghost (p3) ready", + "[002] [16:51:18 UTC] 080 placed Scientist with PAPER to theatre", + "[002] [16:51:21 UTC] 080 placed Artist with SCISSORS to theatre", + "[002] [16:51:25 UTC] 080 placed Robot with DUMMY to factory", + "[002] [16:51:29 UTC] 080 ready", + "[002] [16:51:29 UTC] PHASE 3", + "[002] [16:54:48 UTC] Viper placed Politician with ROCK to square", + "[002] [16:54:49 UTC] Viper placed Robot with PAPER to factory", + "[002] [16:54:49 UTC] 080 placed Politician with PAPER to square", + "[002] [16:54:49 UTC] Viper placed Scientist with SCISSORS to university", + "[002] [16:54:50 UTC] Viper placed Artist with ROCK to theatre", + "[002] [16:54:51 UTC] Ghost placed Politician with SCISSORS to university", + "[002] [16:54:51 UTC] Ghost placed Robot with ROCK to dump", + "[002] [16:54:52 UTC] 080 placed Scientist with SCISSORS to theatre", + "[002] [16:54:52 UTC] Ghost placed Scientist with PAPER to theatre", + "[002] [16:54:52 UTC] Ghost placed Artist with SCISSORS to square", + "[002] [16:54:53 UTC] Viper (p2) ready", + "[002] [16:54:54 UTC] Ghost (p3) ready", + "[002] [16:54:58 UTC] 080 placed Artist with ROCK to theatre", + "[002] [16:55:01 UTC] 080 placed Robot with DUMMY to energy", + "[002] [16:55:02 UTC] 080 ready", + "[002] [16:55:02 UTC] PHASE 3", + "[002] [17:03:06 UTC] Viper placed Politician with ROCK to square", + "[002] [17:03:08 UTC] Viper placed Robot with PAPER to factory", + "[002] [17:03:08 UTC] Viper placed Scientist with SCISSORS to university", + "[002] [17:03:09 UTC] Viper placed Artist with ROCK to theatre", + "[002] [17:03:10 UTC] Ghost placed Politician with SCISSORS to university", + "[002] [17:03:11 UTC] Ghost placed Robot with ROCK to dump", + "[002] [17:03:12 UTC] Ghost placed Scientist with PAPER to theatre", + "[002] [17:03:13 UTC] Ghost placed Artist with SCISSORS to square", + "[002] [17:03:14 UTC] Viper (p2) ready", + "[002] [17:03:15 UTC] Ghost (p3) ready", + "[002] [17:08:40 UTC] 080 placed Politician with SCISSORS to square", + "[002] [17:08:42 UTC] 080 placed Scientist with PAPER to theatre", + "[002] [17:08:46 UTC] 080 placed Artist with ROCK to theatre", + "[002] [17:08:50 UTC] 080 placed Robot with DUMMY to dump", + "[002] [17:08:51 UTC] 080 ready", + "[002] [17:08:51 UTC] PHASE 3", + "[002] [17:09:08 UTC] 080 attached PRODUCT to Scientist", + "[002] [17:09:13 UTC] 080 attached ENERGY to Scientist", + "[002] [17:09:15 UTC] 080 attached RECYCLE to Scientist", + "[002] [17:11:35 UTC] Viper placed Politician with ROCK to square", + "[002] [17:11:36 UTC] Viper placed Robot with PAPER to factory", + "[002] [17:11:37 UTC] Viper placed Scientist with SCISSORS to university", + "[002] [17:11:38 UTC] Viper placed Artist with ROCK to theatre", + "[002] [17:11:39 UTC] Ghost placed Politician with SCISSORS to university", + "[002] [17:11:40 UTC] Ghost placed Robot with ROCK to dump", + "[002] [17:11:41 UTC] Ghost placed Scientist with PAPER to theatre", + "[002] [17:11:42 UTC] Ghost placed Artist with SCISSORS to square", + "[002] [17:11:43 UTC] Viper (p2) ready", + "[002] [17:11:44 UTC] Ghost (p3) ready", + "[002] [17:13:25 UTC] Viper placed Politician with ROCK to square", + "[002] [17:13:26 UTC] Viper placed Robot with PAPER to factory", + "[002] [17:13:26 UTC] Viper placed Scientist with SCISSORS to university", + "[002] [17:13:29 UTC] Viper placed Politician with ROCK to square", + "[002] [17:13:29 UTC] Viper placed Robot with PAPER to factory", + "[002] [17:13:30 UTC] Viper placed Scientist with SCISSORS to university", + "[002] [17:13:34 UTC] Viper placed Politician with ROCK to square", + "[002] [17:13:35 UTC] Viper placed Robot with PAPER to factory", + "[002] [17:13:36 UTC] Viper placed Scientist with SCISSORS to university", + "[002] [17:13:36 UTC] Viper placed Artist with ROCK to theatre", + "[002] [17:13:37 UTC] Ghost placed Politician with SCISSORS to university", + "[002] [17:13:38 UTC] Ghost placed Robot with ROCK to dump", + "[002] [17:13:39 UTC] Ghost placed Scientist with PAPER to theatre" ], "transactions": [], "messages": [ { - "sender": "080", + "sender": "Ghost", + "avatar": "/avatars/ghost.png", + "content": "Hello world!", + "timestamp": 1769964642728 + }, + { + "sender": "Viper", + "avatar": "/avatars/viper.png", + "content": "Hello world!", + "timestamp": 1769964649995 + } + ], + "startTime": 1769964661996, + "displayId": "002" + }, + { + "id": "6fd72553-b8c8-4c3c-ae6e-c9064a858174", + "roomId": "Meta_Zone", + "status": "finished", + "isPrivate": false, + "createdAt": 1769966047997, + "players": [ + { + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", + "name": "080", + "citizenId": "808546", "avatar": "/avatars/golden_avatar.png", - "content": "fsdfsd", - "timestamp": 1769945356994 + "joinedAt": 1769966047997, + "isReady": true + }, + { + "name": "Ghost", + "citizenId": "1002", + "avatar": "/avatars/ghost.png", + "address": "0x3C44...93BC", + "joinedAt": 1769966050107, + "isReady": true + }, + { + "name": "Viper", + "citizenId": "1001", + "avatar": "/avatars/viper.png", + "address": "0x7099...79C8", + "joinedAt": 1769966055398, + "isReady": true } - ] + ], + "maxPlayers": 3, + "bidAmount": 0, + "logs": [ + "[003] [17:14:07 UTC] GAME CREATED BY 080", + "[003] [17:14:10 UTC] Ghost joined", + "[003] [17:14:15 UTC] Viper joined", + "[003] [17:14:29 UTC] Viper placed Politician with ROCK to square", + "[003] [17:14:30 UTC] Viper placed Robot with PAPER to factory", + "[003] [17:14:31 UTC] Viper placed Scientist with SCISSORS to university", + "[003] [17:14:31 UTC] Viper placed Artist with ROCK to theatre", + "[003] [17:14:32 UTC] 080 placed Politician with ROCK to university", + "[003] [17:14:32 UTC] Ghost placed Politician with SCISSORS to university", + "[003] [17:14:32 UTC] Ghost placed Robot with ROCK to dump", + "[003] [17:14:33 UTC] Ghost placed Scientist with PAPER to theatre", + "[003] [17:14:34 UTC] Ghost placed Artist with SCISSORS to square", + "[003] [17:14:34 UTC] Viper (p2) ready", + "[003] [17:14:35 UTC] Ghost (p3) ready", + "[003] [17:14:36 UTC] 080 placed Scientist with SCISSORS to theatre", + "[003] [17:14:39 UTC] 080 placed Artist with PAPER to square", + "[003] [17:14:41 UTC] 080 placed Robot with DUMMY to dump", + "[003] [17:14:43 UTC] 080 ready", + "[003] [17:14:43 UTC] PHASE 3", + "[003] [17:15:56 UTC] Viper placed Politician with ROCK to square", + "[003] [17:15:57 UTC] Viper placed Robot with PAPER to factory", + "[003] [17:15:57 UTC] Viper placed Scientist with SCISSORS to university", + "[003] [17:15:58 UTC] Viper placed Artist with ROCK to theatre", + "[003] [17:15:59 UTC] Ghost placed Politician with SCISSORS to university", + "[003] [17:16:00 UTC] Ghost placed Robot with ROCK to dump", + "[003] [17:16:01 UTC] Ghost placed Scientist with PAPER to theatre", + "[003] [17:16:02 UTC] Ghost placed Artist with SCISSORS to square", + "[003] [17:16:03 UTC] Viper (p2) ready", + "[003] [17:16:04 UTC] Ghost (p3) ready", + "[003] [17:17:07 UTC] 080 placed Politician with PAPER to square", + "[003] [17:17:08 UTC] Recalled paper from map", + "[003] [17:17:10 UTC] 080 placed Politician with PAPER to square", + "[003] [17:17:12 UTC] 080 placed Scientist with ROCK to university", + "[003] [17:17:15 UTC] 080 placed Artist with SCISSORS to theatre", + "[003] [17:17:18 UTC] 080 placed Robot with DUMMY to dump", + "[003] [17:17:18 UTC] 080 ready", + "[003] [17:17:18 UTC] PHASE 3", + "[003] [17:24:33 UTC] 080 BET ON LOSE with Artist", + "[003] [17:24:37 UTC] 080 BET ON WIN with Politician", + "[003] [17:24:52 UTC] 080 BET ON DRAW with Robot", + "[003] [17:26:31 UTC] Viper placed Politician with ROCK to square", + "[003] [17:26:31 UTC] Viper placed Robot with PAPER to factory", + "[003] [17:26:32 UTC] Viper placed Scientist with SCISSORS to university", + "[003] [17:26:32 UTC] 080 placed Politician with ROCK to square", + "[003] [17:26:32 UTC] Viper placed Artist with ROCK to theatre", + "[003] [17:26:33 UTC] Ghost placed Politician with SCISSORS to university", + "[003] [17:26:34 UTC] Ghost placed Robot with ROCK to dump", + "[003] [17:26:34 UTC] Ghost placed Scientist with PAPER to theatre", + "[003] [17:26:35 UTC] 080 placed Scientist with PAPER to university", + "[003] [17:26:35 UTC] Ghost placed Artist with SCISSORS to square", + "[003] [17:26:36 UTC] Viper (p2) ready", + "[003] [17:26:36 UTC] Ghost (p3) ready", + "[003] [17:26:37 UTC] 080 placed Artist with SCISSORS to theatre", + "[003] [17:26:39 UTC] 080 placed Robot with DUMMY to dump", + "[003] [17:26:41 UTC] 080 ready", + "[003] [17:26:41 UTC] PHASE 3", + "[003] [17:26:44 UTC] 080 ready", + "[003] [17:26:44 UTC] PHASE 4", + "[003] [17:26:50 UTC] Viper placed Politician with ROCK to square", + "[003] [17:26:51 UTC] Viper placed Robot with PAPER to factory", + "[003] [17:26:51 UTC] Viper placed Scientist with SCISSORS to university" + ], + "transactions": [], + "messages": [ + { + "sender": "Ghost", + "avatar": "/avatars/ghost.png", + "content": "Hello world!", + "timestamp": 1769966051742 + }, + { + "sender": "Viper", + "avatar": "/avatars/viper.png", + "content": "Hello world!", + "timestamp": 1769966056930 + } + ], + "startTime": 1769966068446, + "displayId": "003" }, { - "id": "70ea30ac-6a74-4d84-9e4a-52e3e12f632e", - "roomId": "Metarchy_Genesis", + "id": "3c5651b2-a0d6-42ca-b44d-5f9a0fb765ee", + "roomId": "Plasma_Grid", "status": "finished", - "createdAt": 1769945693172, + "isPrivate": false, + "createdAt": 1769967110237, + "players": [ + { + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", + "name": "080", + "citizenId": "808546", + "avatar": "/avatars/golden_avatar.png", + "joinedAt": 1769967110237, + "isReady": true + }, + { + "name": "Ghost", + "citizenId": "1002", + "avatar": "/avatars/ghost.png", + "address": "0x3C44...93BC", + "joinedAt": 1769967112499, + "isReady": true + }, + { + "name": "Viper", + "citizenId": "1001", + "avatar": "/avatars/viper.png", + "address": "0x7099...79C8", + "joinedAt": 1769967117678, + "isReady": true + } + ], + "maxPlayers": 3, + "bidAmount": 0, + "logs": [ + "[004] [17:31:50 UTC] GAME CREATED BY 080", + "[004] [17:31:52 UTC] Ghost joined", + "[004] [17:31:57 UTC] Viper joined", + "[004] [17:32:12 UTC] Viper placed Politician with ROCK to square", + "[004] [17:32:12 UTC] Viper placed Robot with PAPER to factory", + "[004] [17:32:13 UTC] Viper placed Scientist with SCISSORS to university", + "[004] [17:32:13 UTC] Viper placed Artist with ROCK to theatre", + "[004] [17:32:14 UTC] 080 placed Politician with PAPER to square", + "[004] [17:32:14 UTC] Ghost placed Politician with SCISSORS to university", + "[004] [17:32:15 UTC] Ghost placed Robot with ROCK to dump", + "[004] [17:32:15 UTC] Ghost placed Scientist with PAPER to theatre", + "[004] [17:32:16 UTC] Ghost placed Artist with SCISSORS to square", + "[004] [17:32:16 UTC] 080 placed Scientist with DUMMY to theatre", + "[004] [17:32:16 UTC] Viper (p2) ready", + "[004] [17:32:17 UTC] Ghost (p3) ready", + "[004] [17:32:22 UTC] 080 placed Artist with ROCK to square", + "[004] [17:32:27 UTC] 080 placed Robot with SCISSORS to dump", + "[004] [17:32:29 UTC] 080 ready", + "[004] [17:32:29 UTC] PHASE 3", + "[004] [17:32:31 UTC] 080 BET ON WIN with Artist", + "[004] [17:32:35 UTC] 080 removed bet from actor", + "[004] [17:32:36 UTC] 080 BET ON WIN with Artist", + "[004] [17:32:42 UTC] 080 BET ON LOSE with Scientist", + "[004] [17:32:51 UTC] 080 removed bet from actor", + "[004] [17:32:59 UTC] 080 removed bet from actor", + "[004] [17:33:00 UTC] 080 BET ON WIN with Robot", + "[004] [17:33:01 UTC] 080 viewing action cards", + "[004] [17:41:55 UTC] Viper placed Politician with ROCK to square", + "[004] [17:41:56 UTC] Viper placed Robot with PAPER to factory", + "[004] [17:41:57 UTC] Viper placed Scientist with SCISSORS to university", + "[004] [17:41:58 UTC] Viper placed Artist with ROCK to theatre", + "[004] [17:41:59 UTC] Ghost placed Politician with SCISSORS to university", + "[004] [17:42:00 UTC] Ghost placed Robot with ROCK to dump", + "[004] [17:42:01 UTC] Ghost placed Scientist with PAPER to theatre", + "[004] [17:42:02 UTC] Ghost placed Artist with SCISSORS to square", + "[004] [17:42:03 UTC] Viper (p2) ready", + "[004] [17:42:04 UTC] Ghost (p3) ready", + "[004] [17:42:20 UTC] Viper placed Politician with ROCK to square", + "[004] [17:42:21 UTC] Viper placed Robot with PAPER to factory", + "[004] [17:42:22 UTC] Viper placed Scientist with SCISSORS to university", + "[004] [17:42:23 UTC] Viper placed Artist with ROCK to theatre", + "[004] [17:42:24 UTC] Ghost placed Politician with SCISSORS to university", + "[004] [17:42:25 UTC] Ghost placed Robot with ROCK to dump", + "[004] [17:42:26 UTC] Ghost placed Scientist with PAPER to theatre", + "[004] [17:42:28 UTC] Ghost placed Artist with SCISSORS to square", + "[004] [17:42:28 UTC] Viper (p2) ready", + "[004] [17:42:29 UTC] Ghost (p3) ready", + "[004] [17:50:31 UTC] Viper placed Politician with ROCK to square", + "[004] [17:50:33 UTC] Viper placed Robot with PAPER to factory", + "[004] [17:50:33 UTC] Viper placed Scientist with SCISSORS to university", + "[004] [17:50:34 UTC] Viper placed Artist with ROCK to theatre", + "[004] [17:50:35 UTC] Ghost placed Politician with SCISSORS to university", + "[004] [17:50:36 UTC] Ghost placed Robot with ROCK to dump", + "[004] [17:50:37 UTC] Ghost placed Scientist with PAPER to theatre", + "[004] [17:50:38 UTC] Ghost placed Artist with SCISSORS to square", + "[004] [17:50:39 UTC] Viper (p2) ready", + "[004] [17:50:41 UTC] Ghost (p3) ready", + "[004] [17:51:44 UTC] Viper placed Politician with ROCK to square", + "[004] [17:51:45 UTC] Viper placed Robot with PAPER to factory", + "[004] [17:51:46 UTC] Viper placed Scientist with SCISSORS to university", + "[004] [17:51:47 UTC] Viper placed Artist with ROCK to theatre", + "[004] [17:51:48 UTC] Ghost placed Politician with SCISSORS to university", + "[004] [17:51:49 UTC] Ghost placed Robot with ROCK to dump", + "[004] [17:51:50 UTC] Ghost placed Scientist with PAPER to theatre", + "[004] [17:51:51 UTC] Ghost placed Artist with SCISSORS to square", + "[004] [17:51:52 UTC] Viper (p2) ready", + "[004] [17:51:53 UTC] Ghost (p3) ready", + "[004] [18:02:34 UTC] Viper placed Politician with ROCK to square", + "[004] [18:02:35 UTC] Viper placed Robot with PAPER to factory", + "[004] [18:02:37 UTC] Viper placed Scientist with SCISSORS to university", + "[004] [18:02:37 UTC] Viper placed Artist with ROCK to theatre", + "[004] [18:02:38 UTC] Ghost placed Politician with SCISSORS to university", + "[004] [18:02:39 UTC] Ghost placed Robot with ROCK to dump", + "[004] [18:02:40 UTC] Ghost placed Scientist with PAPER to theatre", + "[004] [18:02:41 UTC] Ghost placed Artist with SCISSORS to square", + "[004] [18:02:42 UTC] Viper (p2) ready", + "[004] [18:02:43 UTC] Ghost (p3) ready" + ], + "transactions": [], + "messages": [ + { + "sender": "Ghost", + "avatar": "/avatars/ghost.png", + "content": "Hello world!", + "timestamp": 1769967114121 + }, + { + "sender": "Viper", + "avatar": "/avatars/viper.png", + "content": "Hello world!", + "timestamp": 1769967119209 + } + ], + "startTime": 1769967130738, + "displayId": "004" + }, + { + "id": "13beb57e-da5f-41ec-a216-5c9a04d7bfac", + "roomId": "Aura_Flow", + "status": "finished", + "isPrivate": false, + "createdAt": 1769969788685, + "players": [ + { + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", + "name": "080", + "citizenId": "808546", + "avatar": "/avatars/golden_avatar.png", + "joinedAt": 1769969788685, + "isReady": true + }, + { + "name": "Ghost", + "citizenId": "1002", + "avatar": "/avatars/ghost.png", + "address": "0x3C44...93BC", + "joinedAt": 1769969790964, + "isReady": true + }, + { + "name": "Viper", + "citizenId": "1001", + "avatar": "/avatars/viper.png", + "address": "0x7099...79C8", + "joinedAt": 1769969796117, + "isReady": true + } + ], + "maxPlayers": 3, + "bidAmount": 0, + "logs": [ + "[005] [18:16:28 UTC] GAME CREATED BY 080", + "[005] [18:16:30 UTC] Ghost joined", + "[005] [18:16:36 UTC] Viper joined", + "[005] [18:16:50 UTC] Viper placed Politician with ROCK to square", + "[005] [18:16:51 UTC] Viper placed Robot with PAPER to factory", + "[005] [18:16:51 UTC] Viper placed Scientist with SCISSORS to university", + "[005] [18:16:52 UTC] Viper placed Artist with ROCK to theatre", + "[005] [18:16:53 UTC] Ghost placed Politician with SCISSORS to university", + "[005] [18:16:53 UTC] Ghost placed Robot with ROCK to dump", + "[005] [18:16:54 UTC] Ghost placed Scientist with PAPER to theatre", + "[005] [18:16:54 UTC] Ghost placed Artist with SCISSORS to square", + "[005] [18:16:55 UTC] Viper (p2) ready", + "[005] [18:16:56 UTC] Ghost (p3) ready", + "[005] [18:16:56 UTC] 080 placed Politician with PAPER to square", + "[005] [18:17:00 UTC] 080 placed Scientist with ROCK to university", + "[005] [18:17:06 UTC] 080 placed Artist with SCISSORS to square", + "[005] [18:17:08 UTC] Recalled scissors from map", + "[005] [18:17:11 UTC] 080 placed Artist with SCISSORS to theatre", + "[005] [18:17:14 UTC] 080 placed Robot with DUMMY to dump", + "[005] [18:17:15 UTC] 080 ready", + "[005] [18:17:15 UTC] PHASE 3", + "[005] [18:17:26 UTC] 080 BET ON DRAW with Robot", + "[005] [18:17:35 UTC] 080 BET ON WIN with Scientist", + "[005] [18:17:36 UTC] 080 advanced to STOPPING LOCATIONS", + "[005] [18:17:40 UTC] 080 advanced to RELOCATION", + "[005] [18:17:46 UTC] 080 advanced to EXCHANGE", + "[005] [18:17:48 UTC] 080 ready", + "[005] [18:17:48 UTC] PHASE 4", + "[005] [18:37:33 UTC] Viper placed Politician with ROCK to square", + "[005] [18:37:34 UTC] Viper placed Robot with PAPER to factory", + "[005] [18:37:35 UTC] Viper placed Scientist with SCISSORS to university", + "[005] [18:37:35 UTC] 080 placed Politician with PAPER to square", + "[005] [18:37:35 UTC] Viper placed Artist with ROCK to theatre", + "[005] [18:37:36 UTC] Ghost placed Politician with SCISSORS to university", + "[005] [18:37:36 UTC] Ghost placed Robot with ROCK to dump", + "[005] [18:37:37 UTC] Ghost placed Scientist with PAPER to theatre", + "[005] [18:37:38 UTC] Ghost placed Artist with SCISSORS to square", + "[005] [18:37:38 UTC] 080 placed Scientist with SCISSORS to theatre", + "[005] [18:37:38 UTC] Viper (p2) ready", + "[005] [18:37:39 UTC] Ghost (p3) ready", + "[005] [18:37:40 UTC] 080 placed Artist with ROCK to square", + "[005] [18:37:43 UTC] 080 placed Robot with DUMMY to dump", + "[005] [18:37:44 UTC] 080 ready", + "[005] [18:37:44 UTC] PHASE 3", + "[005] [18:37:50 UTC] 080 BET ON DRAW with Robot", + "[005] [18:37:50 UTC] 080 advanced to STOPPING LOCATIONS", + "[005] [18:37:52 UTC] 080 advanced to RELOCATION", + "[005] [18:38:00 UTC] 080 advanced to EXCHANGE", + "[005] [18:38:05 UTC] 080 ready", + "[005] [18:38:05 UTC] PHASE 4", + "[005] [18:38:06 UTC] 080 ready", + "[005] [18:38:06 UTC] PHASE 5", + "[005] [18:38:08 UTC] TURN 2 BEGINS", + "[005] [18:38:17 UTC] Event Result: You discarded 12 (Opponent max: 0). You WIN an Action Card!", + "[005] [18:38:24 UTC] Viper placed Politician with ROCK to square", + "[005] [18:38:25 UTC] Viper placed Robot with PAPER to factory", + "[005] [18:38:25 UTC] Viper placed Scientist with SCISSORS to university", + "[005] [18:38:26 UTC] Viper placed Artist with ROCK to theatre", + "[005] [18:38:27 UTC] Ghost placed Politician with SCISSORS to university", + "[005] [18:38:27 UTC] Ghost placed Robot with ROCK to dump", + "[005] [18:38:28 UTC] Ghost placed Scientist with PAPER to theatre" + ], + "transactions": [], + "messages": [ + { + "sender": "Ghost", + "avatar": "/avatars/ghost.png", + "content": "Hello world!", + "timestamp": 1769969792577 + }, + { + "sender": "Viper", + "avatar": "/avatars/viper.png", + "content": "Hello world!", + "timestamp": 1769969797659 + } + ], + "startTime": 1769969809184, + "displayId": "005" + }, + { + "id": "f8a3dfce-150e-4693-8fcb-f52ea8095e4e", + "displayId": "006", + "roomId": "Prism_Summit", + "status": "finished", + "isPrivate": false, + "createdAt": 1769971334405, "players": [ { "name": "", "address": "", "citizenId": "0000", "avatar": "", - "joinedAt": 1769945693172, + "joinedAt": 1769971334405, + "isReady": true + }, + { + "name": "Ghost", + "citizenId": "1002", + "avatar": "/avatars/ghost.png", + "address": "0x3C44...93BC", + "joinedAt": 1769971336617 + } + ], + "maxPlayers": 3, + "bidAmount": 0, + "logs": [ + "[006] [18:42:14 UTC] GAME CREATED BY ", + "[006] [18:42:16 UTC] Ghost joined" + ], + "transactions": [], + "messages": [ + { + "sender": "Ghost", + "avatar": "/avatars/ghost.png", + "content": "Hello world!", + "timestamp": 1769971338511 + } + ] + }, + { + "id": "0b90a288-3200-419e-a859-0cd768385d44", + "displayId": "007", + "roomId": "Echo_Shell", + "status": "finished", + "isPrivate": false, + "createdAt": 1769971348974, + "players": [ + { + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", + "name": "080", + "citizenId": "808546", + "avatar": "/avatars/golden_avatar.png", + "joinedAt": 1769971348974, "isReady": true }, { @@ -69,7 +614,7 @@ "citizenId": "1002", "avatar": "/avatars/ghost.png", "address": "0x3C44...93BC", - "joinedAt": 1769945695365, + "joinedAt": 1769971351992, "isReady": true }, { @@ -77,14 +622,35 @@ "citizenId": "1001", "avatar": "/avatars/viper.png", "address": "0x7099...79C8", - "joinedAt": 1769945700596, + "joinedAt": 1769971358989, "isReady": true } ], "maxPlayers": 3, "bidAmount": 0, "logs": [ - "Game created by " + "[007] [18:42:28 UTC] GAME CREATED BY 080", + "[007] [18:42:31 UTC] Ghost joined", + "[007] [18:42:38 UTC] Viper joined", + "[007] [18:42:57 UTC] Viper placed Politician with ROCK to square", + "[007] [18:42:58 UTC] Viper placed Robot with PAPER to factory", + "[007] [18:42:59 UTC] Viper placed Scientist with SCISSORS to university", + "[007] [18:42:59 UTC] Viper placed Artist with ROCK to theatre", + "[007] [18:43:00 UTC] Ghost placed Politician with SCISSORS to university", + "[007] [18:43:00 UTC] 080 placed Politician with PAPER to square", + "[007] [18:43:00 UTC] Ghost placed Robot with ROCK to dump", + "[007] [18:43:01 UTC] Ghost placed Scientist with PAPER to theatre", + "[007] [18:43:02 UTC] Ghost placed Artist with SCISSORS to square", + "[007] [18:43:02 UTC] Viper (p2) ready", + "[007] [18:43:03 UTC] 080 placed Scientist with SCISSORS to theatre", + "[007] [18:43:03 UTC] Ghost (p3) ready", + "[007] [18:43:07 UTC] 080 placed Artist with ROCK to square", + "[007] [18:43:09 UTC] 080 placed Robot with DUMMY to dump", + "[007] [18:43:10 UTC] 080 ready", + "[007] [18:43:10 UTC] PHASE 3", + "[007] [18:43:18 UTC] 080 BET ON DRAW with Robot", + "[007] [18:43:19 UTC] 080 advanced to STOPPING LOCATIONS", + "[007] [18:43:21 UTC] 080 advanced to RELOCATION" ], "transactions": [], "messages": [ @@ -92,30 +658,31 @@ "sender": "Ghost", "avatar": "/avatars/ghost.png", "content": "Hello world!", - "timestamp": 1769945696979 + "timestamp": 1769971353980 }, { "sender": "Viper", "avatar": "/avatars/viper.png", "content": "Hello world!", - "timestamp": 1769945702136 + "timestamp": 1769971360998 } ], - "startTime": 1769945715534 + "startTime": 1769971376899 }, { - "id": "b83c39bb-c34b-45ec-8b79-74a0289d8975", - "roomId": "Metarchy_Genesis", + "id": "b8e9f828-a1b2-415b-8373-750a72d78743", + "displayId": "008", + "roomId": "Vector_Summit", "status": "finished", - "isPrivate": true, - "createdAt": 1769946739643, + "isPrivate": false, + "createdAt": 1769971920777, "players": [ { - "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", "name": "080", - "citizenId": "3444", + "citizenId": "808546", "avatar": "/avatars/golden_avatar.png", - "joinedAt": 1769946739643, + "joinedAt": 1769971920777, "isReady": true }, { @@ -123,7 +690,7 @@ "citizenId": "1002", "avatar": "/avatars/ghost.png", "address": "0x3C44...93BC", - "joinedAt": 1769946742000, + "joinedAt": 1769971922960, "isReady": true }, { @@ -131,14 +698,53 @@ "citizenId": "1001", "avatar": "/avatars/viper.png", "address": "0x7099...79C8", - "joinedAt": 1769946748985, + "joinedAt": 1769971928130, "isReady": true } ], "maxPlayers": 3, "bidAmount": 0, "logs": [ - "Game created by 080" + "[008] [18:52:00 UTC] GAME CREATED BY 080", + "[008] [18:52:02 UTC] Ghost joined", + "[008] [18:52:08 UTC] Viper joined", + "[008] [18:52:22 UTC] Viper placed Politician with ROCK to square", + "[008] [18:52:23 UTC] Viper placed Robot with PAPER to factory", + "[008] [18:52:23 UTC] Viper placed Scientist with SCISSORS to university", + "[008] [18:52:24 UTC] Viper placed Artist with ROCK to theatre", + "[008] [18:52:25 UTC] Ghost placed Politician with SCISSORS to university", + "[008] [18:52:25 UTC] Ghost placed Robot with ROCK to dump", + "[008] [18:52:26 UTC] Ghost placed Scientist with PAPER to theatre", + "[008] [18:52:26 UTC] 080 placed Politician with ROCK to square", + "[008] [18:52:26 UTC] Ghost placed Artist with SCISSORS to square", + "[008] [18:52:27 UTC] Viper (p2) ready", + "[008] [18:52:28 UTC] Ghost (p3) ready", + "[008] [18:52:29 UTC] 080 placed Scientist with PAPER to theatre", + "[008] [18:52:34 UTC] 080 placed Artist with SCISSORS to theatre", + "[008] [18:52:37 UTC] 080 placed Robot with DUMMY to factory", + "[008] [18:52:38 UTC] 080 ready", + "[008] [18:52:38 UTC] PHASE 3", + "[008] [18:52:45 UTC] 080 BET ON DRAW with Robot", + "[008] [18:52:46 UTC] 080 advanced to STOPPING LOCATIONS", + "[008] [18:52:52 UTC] 080 advanced to RELOCATION", + "[008] [18:53:03 UTC] 080 advanced to EXCHANGE", + "[008] [18:53:08 UTC] 080 ready", + "[008] [18:53:08 UTC] PHASE 4", + "[008] [18:53:12 UTC] 080 ready", + "[008] [18:53:12 UTC] PHASE 5", + "[008] [18:53:12 UTC] TURN 2 BEGINS", + "[008] [18:53:14 UTC] Event Result: You WIN Glory!", + "[008] [18:53:16 UTC] 080 ready", + "[008] [18:53:16 UTC] PHASE 3", + "[008] [18:53:17 UTC] 080 advanced to STOPPING LOCATIONS", + "[008] [18:53:17 UTC] 080 advanced to RELOCATION", + "[008] [18:53:18 UTC] 080 advanced to EXCHANGE", + "[008] [18:53:18 UTC] 080 ready", + "[008] [18:53:18 UTC] PHASE 4", + "[008] [18:53:19 UTC] 080 ready", + "[008] [18:53:19 UTC] PHASE 5", + "[008] [18:53:19 UTC] TURN 3 BEGINS", + "[008] [18:53:20 UTC] Event Result: You WIN Glory!" ], "transactions": [], "messages": [ @@ -146,30 +752,31 @@ "sender": "Ghost", "avatar": "/avatars/ghost.png", "content": "Hello world!", - "timestamp": 1769946744097 + "timestamp": 1769971924585 }, { "sender": "Viper", "avatar": "/avatars/viper.png", "content": "Hello world!", - "timestamp": 1769946750993 + "timestamp": 1769971929647 } ], - "startTime": 1769946806394 + "startTime": 1769971941177 }, { - "id": "a5c63a41-06f5-40dc-9867-b1142c0dc78a", - "roomId": "Metarchy_Genesis2", + "id": "f6e7c1c7-f305-4f77-a06e-abc9ffb207b4", + "displayId": "009", + "roomId": "Meta_Zone", "status": "finished", "isPrivate": false, - "createdAt": 1769947392779, + "createdAt": 1769972378879, "players": [ { - "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", "name": "080", - "citizenId": "3444", + "citizenId": "808546", "avatar": "/avatars/golden_avatar.png", - "joinedAt": 1769947392779, + "joinedAt": 1769972378879, "isReady": true }, { @@ -177,7 +784,7 @@ "citizenId": "1002", "avatar": "/avatars/ghost.png", "address": "0x3C44...93BC", - "joinedAt": 1769947395003, + "joinedAt": 1769972381090, "isReady": true }, { @@ -185,14 +792,211 @@ "citizenId": "1001", "avatar": "/avatars/viper.png", "address": "0x7099...79C8", - "joinedAt": 1769947400252, + "joinedAt": 1769972387989, "isReady": true } ], "maxPlayers": 3, "bidAmount": 0, "logs": [ - "Game created by 080" + "[009] [18:59:38 UTC] GAME CREATED BY 080", + "[009] [18:59:41 UTC] Ghost joined", + "[009] [18:59:47 UTC] Viper joined", + "[009] [19:00:02 UTC] Viper placed Politician with ROCK to square", + "[009] [19:00:03 UTC] Viper placed Robot with PAPER to factory", + "[009] [19:00:04 UTC] Viper placed Scientist with SCISSORS to university", + "[009] [19:00:05 UTC] Viper placed Artist with ROCK to theatre", + "[009] [19:00:06 UTC] Ghost placed Politician with SCISSORS to university", + "[009] [19:00:08 UTC] Ghost placed Robot with ROCK to dump", + "[009] [19:00:08 UTC] Ghost placed Scientist with PAPER to theatre", + "[009] [19:00:10 UTC] Ghost placed Artist with SCISSORS to square", + "[009] [19:00:10 UTC] Viper (p2) ready", + "[009] [19:00:11 UTC] Ghost (p3) ready", + "[009] [19:00:24 UTC] 080 placed Politician with ROCK to square", + "[009] [19:00:27 UTC] 080 placed Scientist with PAPER to theatre", + "[009] [19:00:31 UTC] 080 placed Artist with SCISSORS to square", + "[009] [19:00:34 UTC] 080 placed Robot with DUMMY to dump", + "[009] [19:00:35 UTC] 080 ready", + "[009] [19:00:35 UTC] PHASE 3", + "[009] [19:00:40 UTC] 080 BET ON DRAW with Robot", + "[009] [19:00:41 UTC] 080 advanced to STOPPING LOCATIONS", + "[009] [19:00:50 UTC] 080 advanced to RELOCATION", + "[009] [19:00:54 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:00:59 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:01:01 UTC] 080 teleported paper to university", + "[009] [19:01:18 UTC] 080 advanced to EXCHANGE", + "[009] [19:01:38 UTC] Viper placed Politician with ROCK to square", + "[009] [19:01:39 UTC] Viper placed Robot with PAPER to factory", + "[009] [19:01:40 UTC] Viper placed Scientist with SCISSORS to university", + "[009] [19:01:40 UTC] Viper placed Artist with ROCK to theatre", + "[009] [19:01:41 UTC] Ghost placed Politician with SCISSORS to university", + "[009] [19:01:41 UTC] Ghost placed Robot with ROCK to dump", + "[009] [19:01:42 UTC] Ghost placed Scientist with PAPER to theatre", + "[009] [19:01:43 UTC] Ghost placed Artist with SCISSORS to square", + "[009] [19:01:44 UTC] Viper (p2) ready", + "[009] [19:01:45 UTC] Ghost (p3) ready", + "[009] [19:04:31 UTC] 080 placed Politician with ROCK to square", + "[009] [19:04:33 UTC] 080 placed Scientist with PAPER to university", + "[009] [19:04:35 UTC] 080 placed Artist with SCISSORS to theatre", + "[009] [19:04:37 UTC] 080 placed Robot with DUMMY to dump", + "[009] [19:04:38 UTC] 080 ready", + "[009] [19:04:38 UTC] PHASE 3", + "[009] [19:04:41 UTC] 080 BET ON DRAW with Robot", + "[009] [19:04:42 UTC] 080 advanced to STOPPING LOCATIONS", + "[009] [19:04:58 UTC] 080 advanced to RELOCATION", + "[009] [19:04:59 UTC] 080 advanced to EXCHANGE", + "[009] [19:05:11 UTC] Viper placed Politician with ROCK to square", + "[009] [19:05:11 UTC] Viper placed Robot with PAPER to factory", + "[009] [19:05:12 UTC] Viper placed Scientist with SCISSORS to university", + "[009] [19:05:13 UTC] Viper placed Artist with ROCK to theatre", + "[009] [19:05:14 UTC] Ghost placed Politician with SCISSORS to university", + "[009] [19:05:15 UTC] Ghost placed Robot with ROCK to dump", + "[009] [19:05:16 UTC] Ghost placed Scientist with PAPER to theatre", + "[009] [19:05:17 UTC] Ghost placed Artist with SCISSORS to square", + "[009] [19:05:17 UTC] Viper (p2) ready", + "[009] [19:05:18 UTC] Ghost (p3) ready", + "[009] [19:05:41 UTC] 080 placed Politician with ROCK to square", + "[009] [19:05:45 UTC] 080 placed Scientist with SCISSORS to theatre", + "[009] [19:05:49 UTC] 080 placed Artist with PAPER to square", + "[009] [19:05:56 UTC] 080 placed Robot with DUMMY to dump", + "[009] [19:05:58 UTC] 080 ready", + "[009] [19:05:58 UTC] PHASE 3", + "[009] [19:06:05 UTC] 080 advanced to STOPPING LOCATIONS", + "[009] [19:06:09 UTC] 080 advanced to RELOCATION", + "[009] [19:06:11 UTC] Selected scissors for teleport... choose a destination.", + "[009] [19:06:16 UTC] 080 teleported scissors to theatre", + "[009] [19:06:25 UTC] Selected scissors for teleport... choose a destination.", + "[009] [19:06:42 UTC] Viper placed Politician with ROCK to square", + "[009] [19:06:43 UTC] Viper placed Robot with PAPER to factory", + "[009] [19:06:43 UTC] 080 placed Politician with ROCK to square", + "[009] [19:06:44 UTC] Viper placed Scientist with SCISSORS to university", + "[009] [19:06:44 UTC] Viper placed Artist with ROCK to theatre", + "[009] [19:06:45 UTC] Ghost placed Politician with SCISSORS to university", + "[009] [19:06:45 UTC] 080 placed Scientist with PAPER to university", + "[009] [19:06:45 UTC] Ghost placed Robot with ROCK to dump", + "[009] [19:06:46 UTC] Ghost placed Scientist with PAPER to theatre", + "[009] [19:06:47 UTC] Ghost placed Artist with SCISSORS to square", + "[009] [19:06:47 UTC] Viper (p2) ready", + "[009] [19:06:48 UTC] 080 placed Artist with SCISSORS to theatre", + "[009] [19:06:48 UTC] Ghost (p3) ready", + "[009] [19:06:51 UTC] 080 placed Robot with DUMMY to energy", + "[009] [19:06:52 UTC] 080 ready", + "[009] [19:06:52 UTC] PHASE 3", + "[009] [19:06:56 UTC] 080 advanced to STOPPING LOCATIONS", + "[009] [19:06:58 UTC] 080 advanced to RELOCATION", + "[009] [19:07:03 UTC] Selected scissors for teleport... choose a destination.", + "[009] [19:07:11 UTC] Selected scissors for teleport... choose a destination.", + "[009] [19:07:14 UTC] Selected rock for teleport... choose a destination.", + "[009] [19:07:18 UTC] Selected scissors for teleport... choose a destination.", + "[009] [19:07:24 UTC] 080 teleported scissors to square", + "[009] [19:07:33 UTC] Selected rock for teleport... choose a destination.", + "[009] [19:07:36 UTC] 080 teleported rock to university", + "[009] [19:07:41 UTC] 080 advanced to EXCHANGE", + "[009] [19:07:44 UTC] 080 exchanged AUTHORITY with Ghost", + "[009] [19:09:40 UTC] Viper placed Politician with ROCK to square", + "[009] [19:09:41 UTC] Viper placed Robot with PAPER to factory", + "[009] [19:09:41 UTC] 080 placed Politician with ROCK to square", + "[009] [19:09:41 UTC] Viper placed Scientist with SCISSORS to university", + "[009] [19:09:42 UTC] Viper placed Artist with ROCK to theatre", + "[009] [19:09:43 UTC] Ghost placed Politician with SCISSORS to university", + "[009] [19:09:43 UTC] Ghost placed Robot with ROCK to dump", + "[009] [19:09:43 UTC] 080 placed Scientist with PAPER to theatre", + "[009] [19:09:44 UTC] Ghost placed Scientist with PAPER to theatre", + "[009] [19:09:44 UTC] Ghost placed Artist with SCISSORS to square", + "[009] [19:09:45 UTC] Viper (p2) ready", + "[009] [19:09:46 UTC] Ghost (p3) ready", + "[009] [19:09:48 UTC] 080 placed Artist with SCISSORS to square", + "[009] [19:09:50 UTC] 080 placed Robot with DUMMY to dump", + "[009] [19:09:52 UTC] 080 ready", + "[009] [19:09:52 UTC] PHASE 3", + "[009] [19:09:55 UTC] 080 advanced to STOPPING LOCATIONS", + "[009] [19:09:57 UTC] 080 advanced to RELOCATION", + "[009] [19:11:09 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:11:13 UTC] Selected scissors for teleport... choose a destination.", + "[009] [19:11:14 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:11:18 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:11:20 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:11:22 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:11:24 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:11:27 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:11:29 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:11:31 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:13:47 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:13:51 UTC] Viper placed Politician with ROCK to square", + "[009] [19:13:52 UTC] Viper placed Robot with PAPER to factory", + "[009] [19:13:52 UTC] 080 placed Politician with ROCK to square", + "[009] [19:13:53 UTC] Viper placed Scientist with SCISSORS to university", + "[009] [19:13:53 UTC] Viper placed Artist with ROCK to theatre", + "[009] [19:13:54 UTC] Ghost placed Politician with SCISSORS to university", + "[009] [19:13:54 UTC] 080 placed Scientist with PAPER to university", + "[009] [19:13:54 UTC] Ghost placed Robot with ROCK to dump", + "[009] [19:13:55 UTC] Ghost placed Scientist with PAPER to theatre", + "[009] [19:13:56 UTC] Ghost placed Artist with SCISSORS to square", + "[009] [19:13:56 UTC] Viper (p2) ready", + "[009] [19:13:56 UTC] 080 placed Artist with SCISSORS to theatre", + "[009] [19:13:57 UTC] Ghost (p3) ready", + "[009] [19:13:59 UTC] 080 placed Robot with DUMMY to dump", + "[009] [19:14:00 UTC] 080 ready", + "[009] [19:14:00 UTC] PHASE 3", + "[009] [19:14:01 UTC] 080 advanced to STOPPING LOCATIONS", + "[009] [19:14:02 UTC] 080 advanced to RELOCATION", + "[009] [19:14:14 UTC] Selected scissors for teleport... choose a destination.", + "[009] [19:17:19 UTC] Viper placed Politician with ROCK to square", + "[009] [19:17:19 UTC] Viper placed Robot with PAPER to factory", + "[009] [19:17:20 UTC] Viper placed Scientist with SCISSORS to university", + "[009] [19:17:20 UTC] 080 placed Politician with ROCK to square", + "[009] [19:17:20 UTC] Viper placed Artist with ROCK to theatre", + "[009] [19:17:21 UTC] Ghost placed Politician with SCISSORS to university", + "[009] [19:17:22 UTC] Ghost placed Robot with ROCK to dump", + "[009] [19:17:22 UTC] Ghost placed Scientist with PAPER to theatre", + "[009] [19:17:23 UTC] 080 placed Scientist with PAPER to theatre", + "[009] [19:17:23 UTC] Ghost placed Artist with SCISSORS to square", + "[009] [19:17:23 UTC] Viper (p2) ready", + "[009] [19:17:24 UTC] Ghost (p3) ready", + "[009] [19:17:26 UTC] 080 placed Artist with SCISSORS to theatre", + "[009] [19:17:28 UTC] 080 placed Robot with DUMMY to dump", + "[009] [19:17:30 UTC] 080 ready", + "[009] [19:17:30 UTC] PHASE 3", + "[009] [19:17:34 UTC] 080 advanced to STOPPING LOCATIONS", + "[009] [19:17:38 UTC] 080 advanced to RELOCATION", + "[009] [19:17:42 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:18:40 UTC] 080 teleported paper to theatre", + "[009] [19:18:41 UTC] Selected paper for teleport... choose a destination.", + "[009] [19:29:05 UTC] Selected scissors for teleport... choose a destination.", + "[009] [19:29:08 UTC] Selected scissors for teleport... choose a destination.", + "[009] [19:29:11 UTC] Selected rock for teleport... choose a destination.", + "[009] [19:29:14 UTC] 080 teleported rock to square", + "[009] [19:29:16 UTC] 080 advanced to EXCHANGE", + "[009] [19:30:13 UTC] Viper placed Politician with ROCK to square", + "[009] [19:30:14 UTC] Viper placed Robot with PAPER to factory", + "[009] [19:30:15 UTC] Viper placed Scientist with SCISSORS to university", + "[009] [19:30:15 UTC] 080 placed Politician with ROCK to square", + "[009] [19:30:15 UTC] Viper placed Artist with ROCK to theatre", + "[009] [19:30:16 UTC] Ghost placed Politician with SCISSORS to university", + "[009] [19:30:16 UTC] Ghost placed Robot with ROCK to dump", + "[009] [19:30:17 UTC] Ghost placed Scientist with PAPER to theatre", + "[009] [19:30:18 UTC] Ghost placed Artist with SCISSORS to square", + "[009] [19:30:18 UTC] 080 placed Scientist with PAPER to theatre", + "[009] [19:30:18 UTC] Viper (p2) ready", + "[009] [19:30:19 UTC] Ghost (p3) ready", + "[009] [19:30:21 UTC] 080 placed Artist with SCISSORS to theatre", + "[009] [19:30:24 UTC] 080 placed Robot with DUMMY to dump", + "[009] [19:30:25 UTC] 080 ready", + "[009] [19:30:25 UTC] PHASE 3", + "[009] [19:30:30 UTC] 080 advanced to STOPPING LOCATIONS", + "[009] [19:30:32 UTC] 080 advanced to RELOCATION", + "[009] [19:30:36 UTC] Selected scissors for teleport... choose a destination.", + "[009] [19:30:42 UTC] 080 teleported scissors to square", + "[009] [19:30:58 UTC] 080 advanced to EXCHANGE", + "[009] [19:31:00 UTC] 080 ready", + "[009] [19:31:00 UTC] PHASE 4", + "[009] [19:31:01 UTC] 080 ready", + "[009] [19:31:01 UTC] PHASE 5", + "[009] [19:31:01 UTC] TURN 2 BEGINS", + "[009] [19:31:06 UTC] Event Result: You WIN Glory!", + "[009] [19:32:01 UTC] Viper placed Politician with ROCK to square", + "[009] [19:32:02 UTC] Viper placed Robot with PAPER to factory", + "[009] [19:32:02 UTC] Viper placed Scientist with SCISSORS to university" ], "transactions": [], "messages": [ @@ -200,30 +1004,31 @@ "sender": "Ghost", "avatar": "/avatars/ghost.png", "content": "Hello world!", - "timestamp": 1769947396608 + "timestamp": 1769972383204 }, { "sender": "Viper", "avatar": "/avatars/viper.png", "content": "Hello world!", - "timestamp": 1769947401785 + "timestamp": 1769972389995 } ], - "startTime": 1769947413318 + "startTime": 1769972401985 }, { - "id": "0012a406-8741-46f0-a14b-0f366e1546bb", - "roomId": "Metarchy_Genesis", + "id": "e5208b64-cd87-4ab9-b376-b866e1d608a7", + "displayId": "010", + "roomId": "Neural_Drift", "status": "finished", "isPrivate": false, - "createdAt": 1769949872744, + "createdAt": 1769974360910, "players": [ { - "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", "name": "080", - "citizenId": "3444", + "citizenId": "808546", "avatar": "/avatars/golden_avatar.png", - "joinedAt": 1769949872744, + "joinedAt": 1769974360910, "isReady": true }, { @@ -231,7 +1036,7 @@ "citizenId": "1002", "avatar": "/avatars/ghost.png", "address": "0x3C44...93BC", - "joinedAt": 1769949874922, + "joinedAt": 1769974363002, "isReady": true }, { @@ -239,14 +1044,49 @@ "citizenId": "1001", "avatar": "/avatars/viper.png", "address": "0x7099...79C8", - "joinedAt": 1769949880209, + "joinedAt": 1769974368231, "isReady": true } ], "maxPlayers": 3, "bidAmount": 0, "logs": [ - "Game created by 080" + "[010] [19:32:40 UTC] GAME CREATED BY 080", + "[010] [19:32:43 UTC] Ghost joined", + "[010] [19:32:48 UTC] Viper joined", + "[010] [19:32:53 UTC] Viper placed Politician with ROCK to square", + "[010] [19:32:54 UTC] Viper placed Robot with PAPER to factory", + "[010] [19:32:54 UTC] Viper placed Scientist with SCISSORS to university", + "[010] [19:32:55 UTC] Viper placed Artist with ROCK to theatre", + "[010] [19:32:56 UTC] Ghost placed Politician with SCISSORS to university", + "[010] [19:32:56 UTC] Ghost placed Robot with ROCK to dump", + "[010] [19:32:57 UTC] Ghost placed Scientist with PAPER to theatre", + "[010] [19:32:58 UTC] 080 placed Politician with ROCK to square", + "[010] [19:32:58 UTC] Ghost placed Artist with SCISSORS to square", + "[010] [19:32:58 UTC] Viper (p2) ready", + "[010] [19:32:59 UTC] Ghost (p3) ready", + "[010] [19:33:02 UTC] 080 placed Scientist with PAPER to theatre", + "[010] [19:33:04 UTC] Recalled rock from map", + "[010] [19:33:07 UTC] 080 placed Politician with ROCK to square", + "[010] [19:33:11 UTC] 080 placed Artist with SCISSORS to square", + "[010] [19:33:15 UTC] 080 placed Robot with DUMMY to dump", + "[010] [19:33:16 UTC] Recalled dummy from map", + "[010] [19:33:19 UTC] 080 placed Robot with DUMMY to energy", + "[010] [19:33:21 UTC] 080 ready", + "[010] [19:33:21 UTC] PHASE 3", + "[010] [19:33:26 UTC] 080 BET ON WIN with Robot", + "[010] [19:33:30 UTC] 080 advanced to STOPPING LOCATIONS", + "[010] [19:33:35 UTC] 080 advanced to RELOCATION", + "[010] [19:33:38 UTC] Selected paper for teleport... choose a destination.", + "[010] [19:33:42 UTC] 080 teleported paper to university", + "[010] [19:33:47 UTC] 080 advanced to EXCHANGE", + "[010] [19:33:51 UTC] 080 exchanged AUTHORITY with Ghost", + "[010] [19:33:54 UTC] 080 ready", + "[010] [19:33:54 UTC] PHASE 4", + "[010] [19:33:55 UTC] 080 ready", + "[010] [19:33:55 UTC] PHASE 5", + "[010] [19:33:55 UTC] TURN 2 BEGINS", + "[010] [19:34:00 UTC] Event Result: You discarded 13 (Opponent max: 3). You WIN an Action Card!" ], "transactions": [], "messages": [ @@ -254,36 +1094,225 @@ "sender": "Ghost", "avatar": "/avatars/ghost.png", "content": "Hello world!", - "timestamp": 1769949876553 + "timestamp": 1769974364691 }, { "sender": "Viper", "avatar": "/avatars/viper.png", "content": "Hello world!", - "timestamp": 1769949881734 - }, + "timestamp": 1769974369745 + } + ], + "startTime": 1769974371262 + }, + { + "id": "edbd9484-2858-416d-bf65-6d2ba4c007d9", + "displayId": "011", + "roomId": "Hyper_Bastion", + "status": "finished", + "isPrivate": false, + "createdAt": 1770030401723, + "players": [ { - "sender": "080", + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", + "name": "080", + "citizenId": "808546", "avatar": "/avatars/golden_avatar.png", - "content": "Hiiiii", - "timestamp": 1769949882780 + "joinedAt": 1770030401723, + "isReady": true + }, + { + "name": "Ghost", + "citizenId": "1002", + "avatar": "/avatars/ghost.png", + "address": "0x3C44...93BC", + "joinedAt": 1770030404442, + "isReady": true + }, + { + "name": "Viper", + "citizenId": "1001", + "avatar": "/avatars/viper.png", + "address": "0x7099...79C8", + "joinedAt": 1770030409776, + "isReady": true } ], - "startTime": 1769949897622 + "maxPlayers": 3, + "bidAmount": 0, + "logs": [ + "[011] [11:06:41 UTC] GAME CREATED BY 080", + "[011] [11:06:44 UTC] Ghost joined", + "[011] [11:06:49 UTC] Viper joined", + "[011] [11:06:56 UTC] Viper placed Politician with ROCK to square", + "[011] [11:06:56 UTC] Viper placed Robot with PAPER to factory", + "[011] [11:06:57 UTC] Viper placed Scientist with SCISSORS to university", + "[011] [11:06:58 UTC] Viper placed Artist with ROCK to theatre", + "[011] [11:06:58 UTC] Ghost placed Politician with SCISSORS to university", + "[011] [11:06:59 UTC] Ghost placed Robot with ROCK to dump", + "[011] [11:06:59 UTC] Ghost placed Scientist with PAPER to theatre", + "[011] [11:07:00 UTC] Ghost placed Artist with SCISSORS to square", + "[011] [11:07:01 UTC] Viper (p2) ready", + "[011] [11:07:01 UTC] Ghost (p3) ready", + "[011] [11:07:05 UTC] 080 placed Politician with ROCK to university", + "[011] [11:07:10 UTC] 080 placed Scientist with PAPER to theatre", + "[011] [11:07:12 UTC] 080 placed Artist with SCISSORS to square", + "[011] [11:07:15 UTC] 080 placed Robot with DUMMY to dump", + "[011] [11:07:17 UTC] 080 ready", + "[011] [11:07:17 UTC] PHASE 3", + "[011] [11:08:58 UTC] 080 BET ON DRAW with Robot", + "[011] [11:09:02 UTC] 080 advanced to STOPPING LOCATIONS", + "[011] [11:09:12 UTC] 080 advanced to RELOCATION", + "[011] [11:09:21 UTC] Selected dummy for teleport... choose a destination.", + "[011] [11:09:25 UTC] 080 teleported dummy to energy", + "[011] [11:09:32 UTC] 080 advanced to EXCHANGE", + "[011] [11:13:01 UTC] Viper placed Politician with ROCK to square", + "[011] [11:13:02 UTC] Viper placed Robot with PAPER to factory", + "[011] [11:13:02 UTC] 080 placed Politician with ROCK to square", + "[011] [11:13:02 UTC] Viper placed Scientist with SCISSORS to university", + "[011] [11:13:03 UTC] Viper placed Artist with ROCK to theatre", + "[011] [11:13:04 UTC] Ghost placed Politician with SCISSORS to university", + "[011] [11:13:04 UTC] Ghost placed Robot with ROCK to dump", + "[011] [11:13:05 UTC] 080 placed Scientist with SCISSORS to theatre", + "[011] [11:13:05 UTC] Ghost placed Scientist with PAPER to theatre", + "[011] [11:13:06 UTC] Ghost placed Artist with SCISSORS to square", + "[011] [11:13:06 UTC] Viper (p2) ready", + "[011] [11:13:07 UTC] Ghost (p3) ready", + "[011] [11:13:12 UTC] 080 placed Artist with DUMMY to square", + "[011] [11:13:14 UTC] 080 placed Robot with PAPER to dump", + "[011] [11:13:15 UTC] 080 ready", + "[011] [11:13:15 UTC] PHASE 3", + "[011] [11:13:18 UTC] 080 advanced to STOPPING LOCATIONS", + "[011] [11:13:18 UTC] 080 advanced to RELOCATION", + "[011] [11:13:22 UTC] 080 advanced to EXCHANGE", + "[011] [11:22:16 UTC] Viper placed Politician with ROCK to square", + "[011] [11:22:17 UTC] Viper placed Robot with PAPER to factory", + "[011] [11:22:18 UTC] Viper placed Scientist with SCISSORS to university", + "[011] [11:22:19 UTC] Viper placed Artist with ROCK to theatre", + "[011] [11:22:20 UTC] Ghost placed Politician with SCISSORS to university", + "[011] [11:22:21 UTC] Ghost placed Robot with ROCK to dump", + "[011] [11:22:22 UTC] Ghost placed Scientist with PAPER to theatre", + "[011] [11:22:23 UTC] Ghost placed Artist with SCISSORS to square", + "[011] [11:22:24 UTC] Viper (p2) ready", + "[011] [11:22:25 UTC] Ghost (p3) ready", + "[011] [11:37:45 UTC] 080 placed Politician with ROCK to square", + "[011] [11:37:47 UTC] 080 placed Scientist with PAPER to university", + "[011] [11:37:49 UTC] 080 placed Artist with SCISSORS to theatre", + "[011] [11:37:52 UTC] 080 placed Robot with DUMMY to dump", + "[011] [11:37:53 UTC] PHASE 3", + "[011] [11:37:53 UTC] 080 ready", + "[011] [11:38:21 UTC] 080 advanced to STOPPING LOCATIONS", + "[011] [11:38:23 UTC] 080 advanced to RELOCATION", + "[011] [11:38:29 UTC] 080 advanced to EXCHANGE", + "[011] [11:41:31 UTC] Viper placed Politician with ROCK to square", + "[011] [11:41:32 UTC] Viper placed Robot with PAPER to factory", + "[011] [11:41:33 UTC] Viper placed Scientist with SCISSORS to university", + "[011] [11:41:34 UTC] Viper placed Artist with ROCK to theatre", + "[011] [11:41:35 UTC] Ghost placed Politician with SCISSORS to university", + "[011] [11:41:36 UTC] Ghost placed Robot with ROCK to dump", + "[011] [11:41:37 UTC] Ghost placed Scientist with PAPER to theatre", + "[011] [11:41:38 UTC] Ghost placed Artist with SCISSORS to square", + "[011] [11:41:39 UTC] Viper (p2) ready", + "[011] [11:41:40 UTC] Ghost (p3) ready", + "[011] [11:42:17 UTC] 080 placed Politician with ROCK to square", + "[011] [11:42:20 UTC] 080 placed Scientist with PAPER to university", + "[011] [11:42:23 UTC] 080 placed Artist with SCISSORS to theatre", + "[011] [11:42:26 UTC] 080 placed Robot with DUMMY to dump", + "[011] [11:42:27 UTC] 080 ready", + "[011] [11:42:27 UTC] PHASE 3", + "[011] [11:42:29 UTC] 080 advanced to STOPPING LOCATIONS", + "[011] [11:42:29 UTC] 080 advanced to RELOCATION", + "[011] [11:42:31 UTC] 080 advanced to EXCHANGE", + "[011] [11:42:44 UTC] 080 exchanged POWER for WISDOM with Ghost", + "[011] [11:58:48 UTC] Viper placed Politician with ROCK to square", + "[011] [11:58:49 UTC] Viper placed Robot with PAPER to factory", + "[011] [11:58:50 UTC] Viper placed Scientist with SCISSORS to university", + "[011] [11:58:51 UTC] Viper placed Artist with ROCK to theatre", + "[011] [11:58:52 UTC] Ghost placed Politician with SCISSORS to university", + "[011] [11:58:53 UTC] Ghost placed Robot with ROCK to dump", + "[011] [11:58:54 UTC] Ghost placed Scientist with PAPER to theatre", + "[011] [11:58:55 UTC] Ghost placed Artist with SCISSORS to square", + "[011] [11:58:56 UTC] Viper (p2) ready", + "[011] [11:58:57 UTC] Ghost (p3) ready", + "[011] [12:01:02 UTC] 080 placed Politician with ROCK to square", + "[011] [12:01:05 UTC] 080 placed Scientist with PAPER to university", + "[011] [12:01:08 UTC] 080 placed Artist with SCISSORS to theatre", + "[011] [12:01:13 UTC] 080 placed Robot with DUMMY to dump", + "[011] [12:01:14 UTC] 080 ready", + "[011] [12:01:14 UTC] PHASE 3", + "[011] [12:01:15 UTC] 080 advanced to STOPPING LOCATIONS", + "[011] [12:01:17 UTC] 080 advanced to RELOCATION", + "[011] [12:01:17 UTC] 080 advanced to EXCHANGE", + "[011] [12:01:23 UTC] 080 exchanged POWER for ART with 080", + "[011] [12:06:26 UTC] 080 ready", + "[011] [12:06:26 UTC] PHASE 4", + "[011] [12:06:27 UTC] 080 ready", + "[011] [12:06:27 UTC] PHASE 5", + "[011] [12:06:33 UTC] Viper placed Politician with ROCK to square", + "[011] [12:06:34 UTC] Viper placed Robot with PAPER to factory", + "[011] [12:06:34 UTC] 080 placed Politician with ROCK to square", + "[011] [12:06:35 UTC] Viper placed Scientist with SCISSORS to university", + "[011] [12:06:35 UTC] Viper placed Artist with ROCK to theatre", + "[011] [12:06:36 UTC] Ghost placed Politician with SCISSORS to university", + "[011] [12:06:36 UTC] Ghost placed Robot with ROCK to dump", + "[011] [12:06:37 UTC] Ghost placed Scientist with PAPER to theatre", + "[011] [12:06:38 UTC] Ghost placed Artist with SCISSORS to square", + "[011] [12:06:38 UTC] 080 placed Scientist with PAPER to theatre", + "[011] [12:06:38 UTC] Viper (p2) ready", + "[011] [12:06:39 UTC] Ghost (p3) ready", + "[011] [12:06:40 UTC] Recalled rock from map", + "[011] [12:06:43 UTC] 080 placed Politician with ROCK to square", + "[011] [12:06:45 UTC] 080 placed Artist with SCISSORS to theatre", + "[011] [12:06:47 UTC] 080 placed Robot with DUMMY to dump", + "[011] [12:06:48 UTC] 080 ready", + "[011] [12:06:48 UTC] PHASE 3", + "[011] [12:07:05 UTC] 080 BET ON LOSE with Politician", + "[011] [12:07:24 UTC] 080 advanced to STOPPING LOCATIONS", + "[011] [12:07:25 UTC] 080 advanced to RELOCATION", + "[011] [12:07:26 UTC] 080 advanced to EXCHANGE", + "[011] [12:08:00 UTC] 080 exchanged POWER for WISDOM with 080", + "[011] [14:47:26 UTC] Viper placed Politician with ROCK to square", + "[011] [14:47:27 UTC] Viper placed Robot with PAPER to factory", + "[011] [14:47:28 UTC] Viper placed Scientist with SCISSORS to university", + "[011] [14:47:29 UTC] Viper placed Artist with ROCK to theatre", + "[011] [14:47:30 UTC] Ghost placed Politician with SCISSORS to university", + "[011] [14:47:31 UTC] Ghost placed Robot with ROCK to dump", + "[011] [14:47:32 UTC] Ghost placed Scientist with PAPER to theatre", + "[011] [14:47:33 UTC] Ghost placed Artist with SCISSORS to square", + "[011] [14:47:34 UTC] Viper (p2) ready", + "[011] [14:47:36 UTC] Ghost (p3) ready" + ], + "transactions": [], + "messages": [ + { + "sender": "Ghost", + "avatar": "/avatars/ghost.png", + "content": "Hello world!", + "timestamp": 1770030406223 + }, + { + "sender": "Viper", + "avatar": "/avatars/viper.png", + "content": "Hello world!", + "timestamp": 1770030411295 + } + ], + "startTime": 1770030412814 }, { - "id": "8c7ea8a2-bb6e-4720-a5bc-2d7a99a902e7", - "roomId": "Metarchy_Genesis", + "id": "f70c4421-8127-4ea9-bb1a-f474ecfa31d9", + "displayId": "012", + "roomId": "Plasma_Summit", "status": "finished", "isPrivate": false, - "createdAt": 1769955067150, + "createdAt": 1770038562185, "players": [ { - "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", "name": "080", - "citizenId": "3444", + "citizenId": "808546", "avatar": "/avatars/golden_avatar.png", - "joinedAt": 1769955067150, + "joinedAt": 1770038562185, "isReady": true }, { @@ -291,7 +1320,7 @@ "citizenId": "1002", "avatar": "/avatars/ghost.png", "address": "0x3C44...93BC", - "joinedAt": 1769955069497, + "joinedAt": 1770038564276, "isReady": true }, { @@ -299,14 +1328,51 @@ "citizenId": "1001", "avatar": "/avatars/viper.png", "address": "0x7099...79C8", - "joinedAt": 1769955074739, + "joinedAt": 1770038571353, "isReady": true } ], "maxPlayers": 3, "bidAmount": 0, "logs": [ - "Game created by 080" + "[012] [13:22:42 UTC] GAME CREATED BY 080", + "[012] [13:22:44 UTC] Ghost joined", + "[012] [13:22:51 UTC] Viper joined", + "[012] [13:22:58 UTC] Viper placed Politician with ROCK to square", + "[012] [13:22:59 UTC] Viper placed Robot with PAPER to factory", + "[012] [13:23:00 UTC] Viper placed Scientist with SCISSORS to university", + "[012] [13:23:01 UTC] Viper placed Artist with ROCK to theatre", + "[012] [13:23:02 UTC] Ghost placed Politician with SCISSORS to university", + "[012] [13:23:03 UTC] Ghost placed Robot with ROCK to dump", + "[012] [13:23:04 UTC] Ghost placed Scientist with PAPER to theatre", + "[012] [13:23:05 UTC] Ghost placed Artist with SCISSORS to square", + "[012] [13:23:06 UTC] Viper (p2) ready", + "[012] [13:23:07 UTC] Ghost (p3) ready", + "[012] [13:23:37 UTC] 080 placed Politician with ROCK to square", + "[012] [13:23:40 UTC] 080 placed Scientist with PAPER to university", + "[012] [13:23:42 UTC] 080 placed Artist with SCISSORS to theatre", + "[012] [13:23:45 UTC] 080 placed Robot with DUMMY to dump", + "[012] [13:23:46 UTC] 080 ready", + "[012] [13:23:46 UTC] PHASE 3", + "[012] [13:23:47 UTC] 080 advanced to STOPPING LOCATIONS", + "[012] [13:23:48 UTC] 080 advanced to RELOCATION", + "[012] [13:23:49 UTC] 080 advanced to EXCHANGE", + "[012] [13:23:58 UTC] 080 ready", + "[012] [13:23:58 UTC] PHASE 4", + "[012] [13:35:39 UTC] 080 ready", + "[012] [13:35:39 UTC] PHASE 5", + "[012] [13:35:39 UTC] TURN 2 BEGINS", + "[012] [13:35:42 UTC] Event Result: You WIN Glory!", + "[012] [13:35:47 UTC] Viper placed Politician with ROCK to square", + "[012] [13:35:48 UTC] Viper placed Robot with PAPER to factory", + "[012] [13:35:49 UTC] Viper placed Scientist with SCISSORS to university", + "[012] [13:35:49 UTC] Viper placed Artist with ROCK to theatre", + "[012] [13:35:50 UTC] Ghost placed Politician with SCISSORS to university", + "[012] [13:35:50 UTC] Ghost placed Robot with ROCK to dump", + "[012] [13:35:51 UTC] Ghost placed Scientist with PAPER to theatre", + "[012] [13:35:52 UTC] Ghost placed Artist with SCISSORS to square", + "[012] [13:35:52 UTC] Viper (p2) ready", + "[012] [13:35:53 UTC] Ghost (p3) ready" ], "transactions": [], "messages": [ @@ -314,37 +1380,39 @@ "sender": "Ghost", "avatar": "/avatars/ghost.png", "content": "Hello world!", - "timestamp": 1769955071175 + "timestamp": 1770038566523 }, { "sender": "Viper", "avatar": "/avatars/viper.png", "content": "Hello world!", - "timestamp": 1769955076256 + "timestamp": 1770038573340 } ], - "startTime": 1769955082713 + "startTime": 1770038575347 }, { - "id": "03f28d00-c9c1-4b6b-8d42-a71764f922e3", - "roomId": "Metarchy_Genesis", - "status": "waiting", + "id": "fe0fe0cd-6fab-4bfd-a103-84691fa6bda3", + "displayId": "013", + "roomId": "Plasma_Pulse", + "status": "finished", "isPrivate": false, - "createdAt": 1769955815056, + "createdAt": 1770043790972, "players": [ { - "name": "", - "address": "", - "citizenId": "0000", - "avatar": "", - "joinedAt": 1769955815056 + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", + "name": "080", + "citizenId": "808546", + "avatar": "/avatars/golden_avatar.png", + "joinedAt": 1770043790972, + "isReady": true }, { "name": "Ghost", "citizenId": "1002", "avatar": "/avatars/ghost.png", "address": "0x3C44...93BC", - "joinedAt": 1769955818036, + "joinedAt": 1770043793064, "isReady": true }, { @@ -352,14 +1420,165 @@ "citizenId": "1001", "avatar": "/avatars/viper.png", "address": "0x7099...79C8", - "joinedAt": 1769955823289, + "joinedAt": 1770043798276, "isReady": true } ], "maxPlayers": 3, "bidAmount": 0, "logs": [ - "Game created by " + "[013] [14:49:50 UTC] GAME CREATED BY 080", + "[013] [14:49:53 UTC] Ghost joined", + "[013] [14:49:58 UTC] Viper joined", + "[013] [14:50:03 UTC] Viper placed Politician with ROCK to square", + "[013] [14:50:04 UTC] Viper placed Robot with PAPER to factory", + "[013] [14:50:05 UTC] Viper placed Scientist with SCISSORS to university", + "[013] [14:50:05 UTC] Viper placed Artist with ROCK to theatre", + "[013] [14:50:06 UTC] Ghost placed Politician with SCISSORS to university", + "[013] [14:50:07 UTC] Ghost placed Robot with ROCK to dump", + "[013] [14:50:07 UTC] 080 placed Politician with ROCK to square", + "[013] [14:50:07 UTC] Ghost placed Scientist with PAPER to theatre", + "[013] [14:50:08 UTC] Ghost placed Artist with SCISSORS to square", + "[013] [14:50:08 UTC] Viper (p2) ready", + "[013] [14:50:09 UTC] Ghost (p3) ready", + "[013] [14:50:10 UTC] 080 placed Scientist with PAPER to university", + "[013] [14:50:13 UTC] 080 placed Artist with SCISSORS to theatre", + "[013] [14:50:16 UTC] 080 placed Robot with DUMMY to dump", + "[013] [14:50:21 UTC] 080 ready", + "[013] [14:50:21 UTC] PHASE 3", + "[013] [14:50:42 UTC] 080 BET ON DRAW with Robot", + "[013] [14:50:45 UTC] 080 advanced to STOPPING LOCATIONS", + "[013] [14:50:47 UTC] 080 advanced to RELOCATION", + "[013] [14:50:51 UTC] 080 advanced to EXCHANGE", + "[013] [14:50:54 UTC] 080 ready", + "[013] [14:50:54 UTC] PHASE 4", + "[013] [15:04:26 UTC] Viper placed Politician with ROCK to square", + "[013] [15:04:27 UTC] Viper placed Robot with PAPER to factory", + "[013] [15:04:28 UTC] Viper placed Scientist with SCISSORS to university", + "[013] [15:04:29 UTC] Viper placed Artist with ROCK to theatre", + "[013] [15:04:30 UTC] Ghost placed Politician with SCISSORS to university", + "[013] [15:04:31 UTC] Ghost placed Robot with ROCK to dump", + "[013] [15:04:32 UTC] Ghost placed Scientist with PAPER to theatre", + "[013] [15:04:33 UTC] Ghost placed Artist with SCISSORS to square", + "[013] [15:04:34 UTC] Viper (p2) ready", + "[013] [15:04:35 UTC] Ghost (p3) ready", + "[013] [15:09:40 UTC] 080 placed Politician with ROCK to square", + "[013] [15:09:42 UTC] 080 placed Scientist with PAPER to theatre", + "[013] [15:09:46 UTC] 080 placed Artist with SCISSORS to square", + "[013] [15:09:48 UTC] 080 placed Robot with DUMMY to factory", + "[013] [15:09:50 UTC] 080 ready", + "[013] [15:09:50 UTC] PHASE 3", + "[013] [15:09:57 UTC] 080 BET ON LOSE with Robot", + "[013] [15:09:58 UTC] 080 advanced to STOPPING LOCATIONS", + "[013] [15:09:59 UTC] 080 advanced to RELOCATION", + "[013] [15:10:00 UTC] 080 advanced to EXCHANGE", + "[013] [15:10:01 UTC] 080 ready", + "[013] [15:10:01 UTC] PHASE 4", + "[013] [15:40:17 UTC] Viper placed Politician with ROCK to square", + "[013] [15:40:18 UTC] Viper placed Robot with PAPER to factory", + "[013] [15:40:19 UTC] Viper placed Scientist with SCISSORS to university", + "[013] [15:40:20 UTC] Viper placed Artist with ROCK to theatre", + "[013] [15:40:21 UTC] Ghost placed Politician with SCISSORS to university", + "[013] [15:40:22 UTC] Ghost placed Robot with ROCK to dump", + "[013] [15:40:23 UTC] Ghost placed Scientist with PAPER to theatre", + "[013] [15:40:24 UTC] Ghost placed Artist with SCISSORS to square", + "[013] [15:40:25 UTC] Viper (p2) ready", + "[013] [15:40:26 UTC] Ghost (p3) ready", + "[013] [15:40:53 UTC] 080 placed Politician with ROCK to square", + "[013] [15:40:55 UTC] 080 placed Scientist with PAPER to theatre", + "[013] [15:40:58 UTC] 080 placed Artist with SCISSORS to theatre", + "[013] [15:41:00 UTC] 080 placed Robot with DUMMY to dump", + "[013] [15:41:01 UTC] 080 ready", + "[013] [15:41:01 UTC] PHASE 3", + "[013] [15:41:04 UTC] 080 advanced to STOPPING LOCATIONS", + "[013] [15:41:05 UTC] 080 advanced to RELOCATION", + "[013] [15:41:07 UTC] 080 advanced to EXCHANGE", + "[013] [15:41:08 UTC] 080 ready", + "[013] [15:41:08 UTC] PHASE 4", + "[013] [15:46:09 UTC] Viper placed Politician with ROCK to square", + "[013] [15:46:10 UTC] Viper placed Robot with PAPER to factory", + "[013] [15:46:11 UTC] Viper placed Scientist with SCISSORS to university", + "[013] [15:46:12 UTC] Viper placed Artist with ROCK to theatre", + "[013] [15:46:13 UTC] Ghost placed Politician with SCISSORS to university", + "[013] [15:46:14 UTC] Ghost placed Robot with ROCK to dump", + "[013] [15:46:15 UTC] Ghost placed Scientist with PAPER to theatre", + "[013] [15:46:16 UTC] Ghost placed Artist with SCISSORS to square", + "[013] [15:46:17 UTC] Viper (p2) ready", + "[013] [15:46:18 UTC] Ghost (p3) ready", + "[013] [15:46:21 UTC] Viper placed Politician with ROCK to square", + "[013] [15:46:22 UTC] Viper placed Robot with PAPER to factory", + "[013] [15:46:23 UTC] Viper placed Scientist with SCISSORS to university", + "[013] [15:46:24 UTC] Viper placed Artist with ROCK to theatre", + "[013] [15:46:25 UTC] Ghost placed Politician with SCISSORS to university", + "[013] [15:46:25 UTC] Ghost placed Robot with ROCK to dump", + "[013] [15:46:26 UTC] Ghost placed Scientist with PAPER to theatre", + "[013] [15:46:27 UTC] Ghost placed Artist with SCISSORS to square", + "[013] [15:46:27 UTC] Viper (p2) ready", + "[013] [15:46:28 UTC] Ghost (p3) ready", + "[013] [15:46:29 UTC] 080 placed Politician with ROCK to square", + "[013] [15:46:31 UTC] 080 placed Scientist with SCISSORS to theatre", + "[013] [15:46:36 UTC] 080 placed Artist with PAPER to square", + "[013] [15:46:39 UTC] 080 placed Robot with DUMMY to energy", + "[013] [15:46:40 UTC] 080 ready", + "[013] [15:46:40 UTC] PHASE 3", + "[013] [15:46:41 UTC] 080 advanced to STOPPING LOCATIONS", + "[013] [15:46:42 UTC] 080 advanced to RELOCATION", + "[013] [15:46:42 UTC] 080 advanced to EXCHANGE", + "[013] [15:46:43 UTC] 080 ready", + "[013] [15:46:43 UTC] PHASE 4", + "[013] [15:51:59 UTC] Viper placed Politician with ROCK to square", + "[013] [15:51:59 UTC] Viper placed Robot with PAPER to factory", + "[013] [15:51:59 UTC] 080 placed Politician with ROCK to square", + "[013] [15:52:00 UTC] Viper placed Scientist with SCISSORS to university", + "[013] [15:52:00 UTC] Viper placed Artist with ROCK to theatre", + "[013] [15:52:01 UTC] Ghost placed Politician with SCISSORS to university", + "[013] [15:52:02 UTC] Ghost placed Robot with ROCK to dump", + "[013] [15:52:02 UTC] 080 placed Scientist with PAPER to theatre", + "[013] [15:52:02 UTC] Ghost placed Scientist with PAPER to theatre", + "[013] [15:52:03 UTC] Ghost placed Artist with SCISSORS to square", + "[013] [15:52:03 UTC] Viper (p2) ready", + "[013] [15:52:04 UTC] Ghost (p3) ready", + "[013] [15:52:06 UTC] 080 placed Artist with SCISSORS to square", + "[013] [15:52:09 UTC] 080 placed Robot with DUMMY to dump", + "[013] [15:52:10 UTC] 080 ready", + "[013] [15:52:10 UTC] PHASE 3", + "[013] [15:52:10 UTC] 080 advanced to STOPPING LOCATIONS", + "[013] [15:52:10 UTC] 080 advanced to RELOCATION", + "[013] [15:52:11 UTC] 080 advanced to EXCHANGE", + "[013] [15:52:11 UTC] 080 ready", + "[013] [15:52:11 UTC] PHASE 4", + "[013] [15:57:15 UTC] Viper placed Politician with ROCK to square", + "[013] [15:57:15 UTC] Viper placed Robot with PAPER to factory", + "[013] [15:57:16 UTC] Viper placed Scientist with SCISSORS to university", + "[013] [15:57:17 UTC] Viper placed Artist with ROCK to theatre", + "[013] [15:57:17 UTC] Ghost placed Politician with SCISSORS to university", + "[013] [15:57:19 UTC] Ghost placed Robot with ROCK to dump", + "[013] [15:57:20 UTC] Ghost placed Scientist with PAPER to theatre", + "[013] [15:57:21 UTC] Ghost placed Artist with SCISSORS to square", + "[013] [15:57:22 UTC] Viper (p2) ready", + "[013] [15:57:23 UTC] Ghost (p3) ready", + "[013] [15:58:17 UTC] Viper placed Politician with ROCK to square", + "[013] [15:58:18 UTC] Viper placed Robot with PAPER to factory", + "[013] [15:58:19 UTC] Viper placed Scientist with SCISSORS to university", + "[013] [15:58:20 UTC] Viper placed Artist with ROCK to theatre", + "[013] [15:58:21 UTC] Ghost placed Politician with SCISSORS to university", + "[013] [15:58:22 UTC] Ghost placed Robot with ROCK to dump", + "[013] [15:58:22 UTC] Ghost placed Scientist with PAPER to theatre", + "[013] [15:58:23 UTC] Ghost placed Artist with SCISSORS to square", + "[013] [15:58:24 UTC] Viper (p2) ready", + "[013] [15:58:24 UTC] Ghost (p3) ready", + "[013] [15:58:26 UTC] 080 placed Politician with ROCK to square", + "[013] [15:58:29 UTC] 080 placed Scientist with PAPER to theatre", + "[013] [15:58:32 UTC] 080 placed Artist with SCISSORS to theatre", + "[013] [15:58:35 UTC] 080 placed Robot with DUMMY to dump", + "[013] [15:58:36 UTC] 080 ready", + "[013] [15:58:36 UTC] PHASE 3", + "[013] [15:58:39 UTC] 080 BET ON DRAW with Robot", + "[013] [15:58:41 UTC] 080 advanced to STOPPING LOCATIONS", + "[013] [15:58:41 UTC] 080 advanced to RELOCATION", + "[013] [15:58:41 UTC] 080 advanced to EXCHANGE", + "[013] [15:58:43 UTC] 080 ready", + "[013] [15:58:43 UTC] PHASE 4" ], "transactions": [], "messages": [ @@ -367,36 +1586,39 @@ "sender": "Ghost", "avatar": "/avatars/ghost.png", "content": "Hello world!", - "timestamp": 1769955819664 + "timestamp": 1770043794728 }, { "sender": "Viper", "avatar": "/avatars/viper.png", "content": "Hello world!", - "timestamp": 1769955824805 + "timestamp": 1770043799797 } - ] + ], + "startTime": 1770043801314 }, { - "id": "eff98ff4-305e-4f52-934a-b2ec10050c53", - "roomId": "Metarchy_Genesis", - "status": "waiting", + "id": "0fc4d1c0-f8c1-4e13-b074-9aadd84de25c", + "displayId": "014", + "roomId": "Void_Pulse", + "status": "finished", "isPrivate": false, - "createdAt": 1769955868649, + "createdAt": 1770129337647, "players": [ { - "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", "name": "080", - "citizenId": "3444", + "citizenId": "808546", "avatar": "/avatars/golden_avatar.png", - "joinedAt": 1769955868649 + "joinedAt": 1770129337647, + "isReady": true }, { "name": "Ghost", "citizenId": "1002", "avatar": "/avatars/ghost.png", "address": "0x3C44...93BC", - "joinedAt": 1769955871557, + "joinedAt": 1770129340325, "isReady": true }, { @@ -404,14 +1626,617 @@ "citizenId": "1001", "avatar": "/avatars/viper.png", "address": "0x7099...79C8", - "joinedAt": 1769955878982, + "joinedAt": 1770129345645, "isReady": true } ], "maxPlayers": 3, "bidAmount": 0, "logs": [ - "Game created by 080" + "[014] [14:35:37 UTC] GAME CREATED BY 080", + "[014] [14:35:40 UTC] Ghost joined", + "[014] [14:35:45 UTC] Viper joined", + "[014] [14:35:53 UTC] Viper placed Politician with ROCK to square", + "[014] [14:35:53 UTC] Viper placed Robot with PAPER to factory", + "[014] [14:35:54 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [14:35:55 UTC] Viper placed Artist with ROCK to theatre", + "[014] [14:35:55 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [14:35:56 UTC] Ghost placed Robot with ROCK to dump", + "[014] [14:35:57 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [14:35:57 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [14:35:58 UTC] Viper (p2) ready", + "[014] [14:35:58 UTC] Ghost (p3) ready", + "[014] [14:37:20 UTC] 080 placed Politician with ROCK to square", + "[014] [14:37:22 UTC] 080 placed Scientist with PAPER to university", + "[014] [14:37:24 UTC] 080 placed Artist with SCISSORS to theatre", + "[014] [14:37:27 UTC] 080 placed Robot with DUMMY to dump", + "[014] [14:37:28 UTC] 080 ready", + "[014] [14:37:28 UTC] PHASE 3", + "[014] [14:37:31 UTC] 080 BET ON DRAW with Robot", + "[014] [14:37:32 UTC] 080 advanced to STOPPING LOCATIONS", + "[014] [14:37:33 UTC] 080 advanced to RELOCATION", + "[014] [14:37:33 UTC] 080 advanced to EXCHANGE", + "[014] [14:37:34 UTC] 080 ready", + "[014] [14:37:34 UTC] PHASE 4", + "[014] [14:52:41 UTC] Viper placed Politician with ROCK to square", + "[014] [14:52:42 UTC] Viper placed Robot with PAPER to factory", + "[014] [14:52:43 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [14:52:43 UTC] Viper placed Artist with ROCK to theatre", + "[014] [14:52:44 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [14:52:45 UTC] Ghost placed Robot with ROCK to dump", + "[014] [14:52:45 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [14:52:46 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [14:52:46 UTC] Viper (p2) ready", + "[014] [14:52:47 UTC] Ghost (p3) ready", + "[014] [15:00:33 UTC] 080 placed Politician with ROCK to square", + "[014] [15:00:40 UTC] 080 placed Scientist with PAPER to university", + "[014] [15:00:43 UTC] 080 placed Artist with SCISSORS to theatre", + "[014] [15:00:45 UTC] 080 placed Robot with DUMMY to energy", + "[014] [15:00:46 UTC] 080 ready", + "[014] [15:00:46 UTC] PHASE 3", + "[014] [15:00:52 UTC] 080 BET ON WIN with Robot", + "[014] [15:00:53 UTC] 080 advanced to STOPPING LOCATIONS", + "[014] [15:00:54 UTC] 080 advanced to RELOCATION", + "[014] [15:00:54 UTC] 080 advanced to EXCHANGE", + "[014] [15:00:55 UTC] 080 ready", + "[014] [15:00:55 UTC] PHASE 4", + "[014] [15:07:20 UTC] Conflict at university_scientist complete.", + "[014] [15:15:06 UTC] Viper placed Politician with ROCK to square", + "[014] [15:15:07 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:15:08 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:15:08 UTC] Viper placed Artist with ROCK to theatre", + "[014] [15:15:09 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [15:15:09 UTC] Ghost placed Robot with ROCK to dump", + "[014] [15:15:10 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [15:15:10 UTC] 080 placed Politician with ROCK to square", + "[014] [15:15:11 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [15:15:11 UTC] Viper (p2) ready", + "[014] [15:15:12 UTC] Ghost (p3) ready", + "[014] [15:15:14 UTC] 080 placed Scientist with PAPER to theatre", + "[014] [15:15:21 UTC] 080 placed Artist with SCISSORS to theatre", + "[014] [15:15:24 UTC] 080 placed Robot with DUMMY to energy", + "[014] [15:15:49 UTC] 080 ready", + "[014] [15:15:49 UTC] PHASE 3", + "[014] [15:15:53 UTC] 080 advanced to STOPPING LOCATIONS", + "[014] [15:15:54 UTC] 080 advanced to RELOCATION", + "[014] [15:15:54 UTC] 080 advanced to EXCHANGE", + "[014] [15:15:54 UTC] 080 ready", + "[014] [15:15:54 UTC] PHASE 4", + "[014] [15:16:00 UTC] 080 ready", + "[014] [15:16:00 UTC] PHASE 5", + "[014] [15:16:02 UTC] TURN 2 BEGINS", + "[014] [15:16:03 UTC] Event Result: You discarded 0 (Opponent max: 0). You lost.", + "[014] [15:16:05 UTC] 080 ready", + "[014] [15:16:05 UTC] PHASE 3", + "[014] [15:16:07 UTC] 080 advanced to STOPPING LOCATIONS", + "[014] [15:16:07 UTC] 080 advanced to RELOCATION", + "[014] [15:16:08 UTC] 080 advanced to EXCHANGE", + "[014] [15:16:08 UTC] 080 ready", + "[014] [15:16:08 UTC] PHASE 4", + "[014] [15:17:25 UTC] Viper placed Politician with ROCK to square", + "[014] [15:17:26 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:17:26 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:17:27 UTC] Viper placed Artist with ROCK to theatre", + "[014] [15:17:27 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [15:17:28 UTC] Ghost placed Robot with ROCK to dump", + "[014] [15:17:29 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [15:17:29 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [15:17:30 UTC] Viper (p2) ready", + "[014] [15:17:30 UTC] Ghost (p3) ready", + "[014] [15:23:06 UTC] Viper placed Politician with ROCK to square", + "[014] [15:23:06 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:23:07 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:23:08 UTC] Viper placed Artist with ROCK to theatre", + "[014] [15:23:09 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [15:23:10 UTC] Ghost placed Robot with ROCK to dump", + "[014] [15:23:11 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [15:23:12 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [15:23:13 UTC] Viper (p2) ready", + "[014] [15:23:14 UTC] Ghost (p3) ready", + "[014] [15:25:02 UTC] Viper placed Politician with ROCK to square", + "[014] [15:25:03 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:25:04 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:25:05 UTC] Viper placed Artist with ROCK to theatre", + "[014] [15:25:06 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [15:25:07 UTC] Ghost placed Robot with ROCK to dump", + "[014] [15:25:08 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [15:25:09 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [15:25:10 UTC] Viper (p2) ready", + "[014] [15:25:11 UTC] Ghost (p3) ready", + "[014] [15:52:56 UTC] Viper placed Politician with ROCK to square", + "[014] [15:52:56 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:52:57 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:52:57 UTC] Viper placed Artist with ROCK to theatre", + "[014] [15:52:58 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [15:52:59 UTC] Ghost placed Robot with ROCK to dump", + "[014] [15:53:00 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [15:53:01 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [15:53:02 UTC] Viper (p2) ready", + "[014] [15:53:03 UTC] Ghost (p3) ready", + "[014] [15:55:37 UTC] Viper placed Politician with ROCK to square", + "[014] [15:55:38 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:55:39 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:55:41 UTC] Viper placed Politician with ROCK to square", + "[014] [15:55:42 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:55:44 UTC] Viper placed Politician with ROCK to square", + "[014] [15:55:45 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:55:45 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:55:46 UTC] Viper placed Artist with ROCK to theatre", + "[014] [15:55:47 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [15:55:47 UTC] Ghost placed Robot with ROCK to dump", + "[014] [15:55:48 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [15:55:48 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [15:55:49 UTC] Viper (p2) ready", + "[014] [15:55:50 UTC] Ghost (p3) ready", + "[014] [15:55:53 UTC] Viper placed Politician with ROCK to square", + "[014] [15:55:54 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:55:56 UTC] Viper placed Politician with ROCK to square", + "[014] [15:55:58 UTC] Viper placed Politician with ROCK to square", + "[014] [15:56:01 UTC] Viper placed Politician with ROCK to square", + "[014] [15:56:02 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:56:03 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:56:04 UTC] Viper placed Artist with ROCK to theatre", + "[014] [15:56:05 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [15:56:06 UTC] Ghost placed Robot with ROCK to dump", + "[014] [15:56:06 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [15:56:07 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [15:56:08 UTC] Viper (p2) ready", + "[014] [15:56:08 UTC] Ghost (p3) ready", + "[014] [15:56:14 UTC] Viper placed Politician with ROCK to square", + "[014] [15:56:15 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:56:15 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:56:16 UTC] Viper placed Artist with ROCK to theatre", + "[014] [15:56:18 UTC] Viper placed Politician with ROCK to square", + "[014] [15:56:19 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:56:21 UTC] Viper placed Politician with ROCK to square", + "[014] [15:56:23 UTC] Viper placed Politician with ROCK to square", + "[014] [15:56:24 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:56:26 UTC] Viper placed Politician with ROCK to square", + "[014] [15:56:28 UTC] Viper placed Politician with ROCK to square", + "[014] [15:56:29 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:56:30 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:56:30 UTC] Viper placed Artist with ROCK to theatre", + "[014] [15:56:31 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [15:56:32 UTC] Ghost placed Robot with ROCK to dump", + "[014] [15:56:32 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [15:56:33 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [15:56:33 UTC] Viper (p2) ready", + "[014] [15:56:34 UTC] Ghost (p3) ready", + "[014] [15:57:09 UTC] Viper placed Politician with ROCK to square", + "[014] [15:57:09 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:57:10 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:57:11 UTC] Viper placed Artist with ROCK to theatre", + "[014] [15:57:12 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [15:57:13 UTC] Ghost placed Robot with ROCK to dump", + "[014] [15:57:14 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [15:57:15 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [15:57:16 UTC] Viper (p2) ready", + "[014] [15:57:17 UTC] Ghost (p3) ready", + "[014] [15:58:35 UTC] Viper placed Politician with ROCK to square", + "[014] [15:58:37 UTC] Viper placed Politician with ROCK to square", + "[014] [15:58:38 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:58:40 UTC] Viper placed Politician with ROCK to square", + "[014] [15:58:40 UTC] Viper placed Robot with PAPER to factory", + "[014] [15:58:41 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [15:58:42 UTC] Viper placed Artist with ROCK to theatre", + "[014] [15:58:42 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [15:58:43 UTC] Ghost placed Robot with ROCK to dump", + "[014] [15:58:44 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [15:58:44 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [15:58:45 UTC] Viper (p2) ready", + "[014] [15:58:46 UTC] Ghost (p3) ready", + "[014] [16:00:30 UTC] Viper placed Politician with ROCK to square", + "[014] [16:00:30 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:00:33 UTC] Viper placed Politician with ROCK to square", + "[014] [16:00:34 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:00:35 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:00:36 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:00:37 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:00:38 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:00:39 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:00:40 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:00:41 UTC] Viper (p2) ready", + "[014] [16:00:42 UTC] Ghost (p3) ready", + "[014] [16:05:19 UTC] Viper placed Politician with ROCK to square", + "[014] [16:05:20 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:05:20 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:05:21 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:05:22 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:05:23 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:05:24 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:05:25 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:05:26 UTC] Viper (p2) ready", + "[014] [16:05:27 UTC] Ghost (p3) ready", + "[014] [16:06:18 UTC] Viper placed Politician with ROCK to square", + "[014] [16:06:19 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:06:21 UTC] Viper placed Politician with ROCK to square", + "[014] [16:06:22 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:06:22 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:06:23 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:06:24 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:06:24 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:06:25 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:06:26 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:06:27 UTC] Viper (p2) ready", + "[014] [16:06:28 UTC] Ghost (p3) ready", + "[014] [16:10:33 UTC] Viper placed Politician with ROCK to square", + "[014] [16:10:34 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:10:35 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:10:35 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:10:36 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:10:36 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:10:37 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:10:38 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:10:38 UTC] Viper (p2) ready", + "[014] [16:10:39 UTC] Ghost (p3) ready", + "[014] [16:18:24 UTC] Viper placed Politician with ROCK to square", + "[014] [16:18:24 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:18:25 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:18:26 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:18:27 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:18:28 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:18:29 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:18:30 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:18:31 UTC] Viper (p2) ready", + "[014] [16:18:32 UTC] Ghost (p3) ready", + "[014] [16:24:04 UTC] Viper placed Politician with ROCK to square", + "[014] [16:24:04 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:24:05 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:24:06 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:24:06 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:24:07 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:24:07 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:24:08 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:24:09 UTC] Viper (p2) ready", + "[014] [16:24:09 UTC] Ghost (p3) ready", + "[014] [16:24:32 UTC] 080 placed Politician with ROCK to square", + "[014] [16:24:35 UTC] 080 placed Scientist with DUMMY to theatre", + "[014] [16:24:39 UTC] 080 placed Artist with PAPER to square", + "[014] [16:24:42 UTC] 080 placed Robot with SCISSORS to factory", + "[014] [16:24:43 UTC] 080 ready", + "[014] [16:24:43 UTC] PHASE 3", + "[014] [16:25:33 UTC] Viper placed Politician with ROCK to square", + "[014] [16:25:34 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:25:34 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:25:35 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:25:35 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:25:38 UTC] Viper placed Politician with ROCK to square", + "[014] [16:25:40 UTC] Viper placed Politician with ROCK to square", + "[014] [16:25:41 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:25:42 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:25:43 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:25:44 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:25:45 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:25:46 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:25:47 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:25:48 UTC] Viper (p2) ready", + "[014] [16:25:49 UTC] Ghost (p3) ready", + "[014] [16:27:04 UTC] Viper placed Politician with ROCK to square", + "[014] [16:27:04 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:27:05 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:27:05 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:27:06 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:27:07 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:27:09 UTC] Viper placed Politician with ROCK to square", + "[014] [16:27:10 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:27:10 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:27:11 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:27:12 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:27:13 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:27:14 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:27:15 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:27:16 UTC] Viper (p2) ready", + "[014] [16:27:17 UTC] Ghost (p3) ready", + "[014] [16:29:45 UTC] Viper placed Politician with ROCK to square", + "[014] [16:29:46 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:29:46 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:29:47 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:29:48 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:29:48 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:29:49 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:29:49 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:29:50 UTC] Viper (p2) ready", + "[014] [16:29:51 UTC] Ghost (p3) ready", + "[014] [16:30:23 UTC] Viper placed Politician with ROCK to square", + "[014] [16:30:24 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:30:24 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:30:25 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:30:26 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:30:28 UTC] Viper placed Politician with ROCK to square", + "[014] [16:30:29 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:30:30 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:30:30 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:30:31 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:30:32 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:30:32 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:30:33 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:30:33 UTC] Viper (p2) ready", + "[014] [16:30:34 UTC] Ghost (p3) ready", + "[014] [16:30:39 UTC] Viper placed Politician with ROCK to square", + "[014] [16:30:40 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:30:40 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:30:41 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:30:42 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:30:42 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:30:43 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:30:43 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:30:44 UTC] Viper (p2) ready", + "[014] [16:30:45 UTC] Ghost (p3) ready", + "[014] [16:31:36 UTC] Viper placed Politician with ROCK to square", + "[014] [16:31:37 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:31:37 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:31:38 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:31:38 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:31:41 UTC] Viper placed Politician with ROCK to square", + "[014] [16:31:41 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:31:44 UTC] Viper placed Politician with ROCK to square", + "[014] [16:31:45 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:31:45 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:31:46 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:31:46 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:31:47 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:31:48 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:31:50 UTC] Viper placed Politician with ROCK to square", + "[014] [16:31:50 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:31:51 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:31:52 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:31:53 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:31:54 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:31:55 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:31:56 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:31:57 UTC] Viper (p2) ready", + "[014] [16:31:58 UTC] Ghost (p3) ready", + "[014] [16:32:43 UTC] Viper placed Politician with ROCK to square", + "[014] [16:32:44 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:32:44 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:32:45 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:32:46 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:32:46 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:32:47 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:32:48 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:32:48 UTC] Viper (p2) ready", + "[014] [16:32:49 UTC] Ghost (p3) ready", + "[014] [16:34:01 UTC] Viper placed Politician with ROCK to square", + "[014] [16:34:03 UTC] Viper placed Politician with ROCK to square", + "[014] [16:34:04 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:34:04 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:34:05 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:34:06 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:34:06 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:34:07 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:34:08 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:34:08 UTC] Viper (p2) ready", + "[014] [16:34:09 UTC] Ghost (p3) ready", + "[014] [16:37:05 UTC] Viper placed Politician with ROCK to square", + "[014] [16:37:06 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:37:07 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:37:09 UTC] Viper placed Politician with ROCK to square", + "[014] [16:37:10 UTC] Viper placed Robot with PAPER to factory", + "[014] [16:37:11 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [16:37:12 UTC] Viper placed Artist with ROCK to theatre", + "[014] [16:37:13 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [16:37:14 UTC] Ghost placed Robot with ROCK to dump", + "[014] [16:37:15 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [16:37:16 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [16:37:17 UTC] Viper (p2) ready", + "[014] [16:37:18 UTC] Ghost (p3) ready", + "[014] [17:38:52 UTC] Viper placed Politician with ROCK to square", + "[014] [17:38:52 UTC] Viper placed Robot with PAPER to factory", + "[014] [17:38:53 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [17:38:53 UTC] Viper placed Artist with ROCK to theatre", + "[014] [17:38:54 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [17:38:55 UTC] Ghost placed Robot with ROCK to dump", + "[014] [17:38:55 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [17:38:56 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [17:38:56 UTC] Viper (p2) ready", + "[014] [17:38:57 UTC] Ghost (p3) ready", + "[014] [17:43:46 UTC] Viper placed Politician with ROCK to square", + "[014] [17:43:47 UTC] Viper placed Robot with PAPER to factory", + "[014] [17:43:48 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [17:43:48 UTC] Viper placed Artist with ROCK to theatre", + "[014] [17:43:49 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [17:43:50 UTC] Ghost placed Robot with ROCK to dump", + "[014] [17:43:50 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [17:43:51 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [17:43:51 UTC] Viper (p2) ready", + "[014] [17:43:52 UTC] Ghost (p3) ready", + "[014] [17:45:30 UTC] Viper placed Politician with ROCK to square", + "[014] [17:45:31 UTC] Viper placed Robot with PAPER to factory", + "[014] [17:45:32 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [17:45:33 UTC] Viper placed Artist with ROCK to theatre", + "[014] [17:45:34 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [17:45:35 UTC] Ghost placed Robot with ROCK to dump", + "[014] [17:45:36 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [17:45:37 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [17:45:38 UTC] Viper (p2) ready", + "[014] [17:45:39 UTC] Ghost (p3) ready", + "[014] [17:45:43 UTC] Viper placed Politician with ROCK to square", + "[014] [17:45:43 UTC] Viper placed Robot with PAPER to factory", + "[014] [17:45:44 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [17:45:45 UTC] Viper placed Artist with ROCK to theatre", + "[014] [17:45:46 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [17:45:47 UTC] Ghost placed Robot with ROCK to dump", + "[014] [17:45:48 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [17:45:49 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [17:45:50 UTC] Viper (p2) ready", + "[014] [17:45:51 UTC] Ghost (p3) ready", + "[014] [17:49:45 UTC] Viper placed Politician with ROCK to square", + "[014] [17:49:46 UTC] Viper placed Robot with PAPER to factory", + "[014] [17:49:46 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [17:49:47 UTC] Viper placed Artist with ROCK to theatre", + "[014] [17:49:47 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [17:49:48 UTC] Ghost placed Robot with ROCK to dump", + "[014] [17:49:49 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [17:49:50 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [17:49:51 UTC] Viper (p2) ready", + "[014] [17:49:52 UTC] Ghost (p3) ready", + "[014] [18:00:30 UTC] Viper placed Politician with ROCK to square", + "[014] [18:00:30 UTC] Viper placed Robot with PAPER to factory", + "[014] [18:00:31 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [18:00:32 UTC] Viper placed Artist with ROCK to theatre", + "[014] [18:00:33 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [18:00:34 UTC] Ghost placed Robot with ROCK to dump", + "[014] [18:00:35 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [18:00:36 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [18:00:37 UTC] Viper (p2) ready", + "[014] [18:00:38 UTC] Ghost (p3) ready", + "[014] [18:01:00 UTC] 080 placed Politician with ROCK to square", + "[014] [18:01:03 UTC] 080 placed Scientist with PAPER to university", + "[014] [18:01:06 UTC] 080 placed Artist with SCISSORS to theatre", + "[014] [18:01:08 UTC] 080 placed Robot with DUMMY to dump", + "[014] [18:01:09 UTC] 080 ready", + "[014] [18:01:09 UTC] PHASE 3", + "[014] [18:01:13 UTC] 080 advanced to STOPPING LOCATIONS", + "[014] [18:01:13 UTC] 080 advanced to RELOCATION", + "[014] [18:01:13 UTC] 080 advanced to EXCHANGE", + "[014] [18:01:14 UTC] 080 ready", + "[014] [18:01:14 UTC] PHASE 4", + "[014] [18:17:21 UTC] Viper placed Politician with ROCK to square", + "[014] [18:17:22 UTC] Viper placed Robot with PAPER to factory", + "[014] [18:17:22 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [18:17:23 UTC] Viper placed Artist with ROCK to theatre", + "[014] [18:17:24 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [18:17:24 UTC] Ghost placed Robot with ROCK to dump", + "[014] [18:17:24 UTC] 080 placed Politician with ROCK to square", + "[014] [18:17:25 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [18:17:26 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [18:17:26 UTC] Viper (p2) ready", + "[014] [18:17:27 UTC] Ghost (p3) ready", + "[014] [18:17:27 UTC] 080 placed Scientist with PAPER to theatre", + "[014] [18:17:30 UTC] 080 placed Artist with SCISSORS to theatre", + "[014] [18:17:33 UTC] 080 placed Robot with DUMMY to dump", + "[014] [18:17:33 UTC] 080 ready", + "[014] [18:17:33 UTC] PHASE 3", + "[014] [18:17:51 UTC] 080 advanced to STOPPING LOCATIONS", + "[014] [18:17:52 UTC] 080 advanced to RELOCATION", + "[014] [18:17:53 UTC] 080 advanced to EXCHANGE", + "[014] [18:17:53 UTC] 080 ready", + "[014] [18:17:53 UTC] PHASE 4", + "[014] [18:18:00 UTC] Viper placed Politician with ROCK to square", + "[014] [18:18:01 UTC] Viper placed Robot with PAPER to factory", + "[014] [18:18:02 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [18:18:03 UTC] Viper placed Artist with ROCK to theatre", + "[014] [18:18:04 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [18:18:05 UTC] Ghost placed Robot with ROCK to dump", + "[014] [18:18:06 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [18:18:07 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [18:18:08 UTC] Viper (p2) ready", + "[014] [18:18:09 UTC] Ghost (p3) ready", + "[014] [18:18:54 UTC] Viper placed Politician with ROCK to square", + "[014] [18:18:55 UTC] Viper placed Robot with PAPER to factory", + "[014] [18:18:56 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [18:18:57 UTC] Viper placed Artist with ROCK to theatre", + "[014] [18:18:58 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [18:18:59 UTC] Ghost placed Robot with ROCK to dump", + "[014] [18:19:00 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [18:19:01 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [18:19:02 UTC] Viper (p2) ready", + "[014] [18:19:03 UTC] Ghost (p3) ready", + "[014] [18:19:15 UTC] Viper placed Politician with ROCK to square", + "[014] [18:19:16 UTC] Viper placed Robot with PAPER to factory", + "[014] [18:19:16 UTC] 080 placed Politician with ROCK to square", + "[014] [18:19:17 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [18:19:17 UTC] Viper placed Artist with ROCK to theatre", + "[014] [18:19:18 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [18:19:18 UTC] Ghost placed Robot with ROCK to dump", + "[014] [18:19:19 UTC] 080 placed Scientist with PAPER to university", + "[014] [18:19:19 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [18:19:20 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [18:19:20 UTC] Viper (p2) ready", + "[014] [18:19:21 UTC] Ghost (p3) ready", + "[014] [18:19:21 UTC] 080 placed Artist with SCISSORS to theatre", + "[014] [18:19:23 UTC] 080 placed Robot with DUMMY to dump", + "[014] [18:19:26 UTC] 080 ready", + "[014] [18:19:26 UTC] PHASE 3", + "[014] [18:19:27 UTC] 080 advanced to STOPPING LOCATIONS", + "[014] [18:19:28 UTC] 080 advanced to RELOCATION", + "[014] [18:19:28 UTC] 080 advanced to EXCHANGE", + "[014] [18:19:29 UTC] 080 ready", + "[014] [18:19:29 UTC] PHASE 4", + "[014] [18:20:24 UTC] Viper placed Politician with ROCK to square", + "[014] [18:20:25 UTC] Viper placed Robot with PAPER to factory", + "[014] [18:20:25 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [18:20:26 UTC] 080 placed Politician with ROCK to square", + "[014] [18:20:26 UTC] Viper placed Artist with ROCK to theatre", + "[014] [18:20:26 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [18:20:27 UTC] Ghost placed Robot with ROCK to dump", + "[014] [18:20:28 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [18:20:28 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [18:20:29 UTC] 080 placed Scientist with PAPER to university", + "[014] [18:20:29 UTC] Viper (p2) ready", + "[014] [18:20:29 UTC] Ghost (p3) ready", + "[014] [18:20:32 UTC] 080 placed Artist with SCISSORS to theatre", + "[014] [18:20:34 UTC] 080 placed Robot with DUMMY to dump", + "[014] [18:20:35 UTC] 080 ready", + "[014] [18:20:35 UTC] PHASE 3", + "[014] [18:20:37 UTC] 080 advanced to STOPPING LOCATIONS", + "[014] [18:20:37 UTC] 080 advanced to RELOCATION", + "[014] [18:20:38 UTC] 080 advanced to EXCHANGE", + "[014] [18:20:39 UTC] 080 ready", + "[014] [18:20:39 UTC] PHASE 4", + "[014] [18:21:22 UTC] Viper placed Politician with ROCK to square", + "[014] [18:21:23 UTC] Viper placed Robot with PAPER to factory", + "[014] [18:21:23 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [18:21:24 UTC] Viper placed Artist with ROCK to theatre", + "[014] [18:21:25 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [18:21:25 UTC] Ghost placed Robot with ROCK to dump", + "[014] [18:21:26 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [18:21:27 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [18:21:27 UTC] 080 placed Politician with ROCK to square", + "[014] [18:21:27 UTC] Viper (p2) ready", + "[014] [18:21:28 UTC] Ghost (p3) ready", + "[014] [18:21:31 UTC] 080 placed Scientist with PAPER to university", + "[014] [18:21:33 UTC] 080 placed Artist with SCISSORS to theatre", + "[014] [18:21:35 UTC] 080 placed Robot with DUMMY to energy", + "[014] [18:21:36 UTC] 080 ready", + "[014] [18:21:36 UTC] PHASE 3", + "[014] [18:21:36 UTC] 080 advanced to STOPPING LOCATIONS", + "[014] [18:21:37 UTC] 080 advanced to RELOCATION", + "[014] [18:21:37 UTC] 080 advanced to EXCHANGE", + "[014] [18:21:38 UTC] 080 ready", + "[014] [18:21:38 UTC] PHASE 4", + "[014] [18:22:43 UTC] Viper placed Politician with ROCK to square", + "[014] [18:22:44 UTC] Viper placed Robot with PAPER to factory", + "[014] [18:22:45 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [18:22:46 UTC] Viper placed Artist with ROCK to theatre", + "[014] [18:22:47 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [18:22:48 UTC] Ghost placed Robot with ROCK to dump", + "[014] [18:22:49 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [18:22:50 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [18:22:51 UTC] Viper (p2) ready", + "[014] [18:22:52 UTC] Ghost (p3) ready", + "[014] [18:23:09 UTC] Viper placed Politician with ROCK to square", + "[014] [18:23:09 UTC] Viper placed Robot with PAPER to factory", + "[014] [18:23:10 UTC] Viper placed Scientist with SCISSORS to university", + "[014] [18:23:10 UTC] 080 placed Politician with ROCK to square", + "[014] [18:23:11 UTC] Viper placed Artist with ROCK to theatre", + "[014] [18:23:11 UTC] Ghost placed Politician with SCISSORS to university", + "[014] [18:23:12 UTC] Ghost placed Robot with ROCK to dump", + "[014] [18:23:12 UTC] Ghost placed Scientist with PAPER to theatre", + "[014] [18:23:13 UTC] 080 placed Scientist with PAPER to university", + "[014] [18:23:13 UTC] Ghost placed Artist with SCISSORS to square", + "[014] [18:23:14 UTC] Viper (p2) ready", + "[014] [18:23:14 UTC] Ghost (p3) ready", + "[014] [18:23:15 UTC] 080 placed Artist with SCISSORS to theatre", + "[014] [18:23:17 UTC] 080 placed Robot with DUMMY to dump", + "[014] [18:23:19 UTC] 080 ready", + "[014] [18:23:19 UTC] PHASE 3", + "[014] [18:23:20 UTC] 080 advanced to STOPPING LOCATIONS", + "[014] [18:23:21 UTC] 080 advanced to RELOCATION", + "[014] [18:23:24 UTC] 080 advanced to EXCHANGE", + "[014] [18:23:25 UTC] 080 ready", + "[014] [18:23:25 UTC] PHASE 4", + "[014] [18:23:26 UTC] 080 ready", + "[014] [18:23:26 UTC] PHASE 5", + "[014] [18:23:26 UTC] TURN 2 BEGINS", + "[014] [18:23:27 UTC] Event Result: You discarded 0 (Opponent max: 1). You lost.", + "[014] [18:23:29 UTC] 080 ready", + "[014] [18:23:29 UTC] PHASE 3", + "[014] [18:23:29 UTC] 080 advanced to STOPPING LOCATIONS", + "[014] [18:23:29 UTC] 080 advanced to RELOCATION", + "[014] [18:23:30 UTC] 080 advanced to EXCHANGE", + "[014] [18:23:31 UTC] 080 ready", + "[014] [18:23:31 UTC] PHASE 4" ], "transactions": [], "messages": [ @@ -419,29 +2244,31 @@ "sender": "Ghost", "avatar": "/avatars/ghost.png", "content": "Hello world!", - "timestamp": 1769955873993 + "timestamp": 1770129342067 }, { "sender": "Viper", "avatar": "/avatars/viper.png", "content": "Hello world!", - "timestamp": 1769955881008 + "timestamp": 1770129347171 } - ] + ], + "startTime": 1770129348711 }, { - "id": "1a3bcb39-576b-4b71-b9c9-57af2176c715", - "roomId": "Metarchy_Genesis", - "status": "starting", + "id": "f5c8e42f-afa1-484c-8435-f3f9d74cee5e", + "displayId": "015", + "roomId": "Vector_Grid", + "status": "playing", "isPrivate": false, - "createdAt": 1769956379858, + "createdAt": 1770144460576, "players": [ { - "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "address": "0x4bfd988bf4b24ccf0788d20c99b89fef040809dd", "name": "080", - "citizenId": "3444", + "citizenId": "808546", "avatar": "/avatars/golden_avatar.png", - "joinedAt": 1769956379858, + "joinedAt": 1770144460576, "isReady": true }, { @@ -449,7 +2276,7 @@ "citizenId": "1002", "avatar": "/avatars/ghost.png", "address": "0x3C44...93BC", - "joinedAt": 1769956382047, + "joinedAt": 1770144463114, "isReady": true }, { @@ -457,14 +2284,26 @@ "citizenId": "1001", "avatar": "/avatars/viper.png", "address": "0x7099...79C8", - "joinedAt": 1769956387364, + "joinedAt": 1770144470625, "isReady": true } ], "maxPlayers": 3, "bidAmount": 0, "logs": [ - "Game created by 080" + "[015] [18:47:40 UTC] GAME CREATED BY 080", + "[015] [18:47:43 UTC] Ghost joined", + "[015] [18:47:50 UTC] Viper joined", + "[015] [18:47:57 UTC] Viper placed Politician with ROCK to square", + "[015] [18:47:58 UTC] Viper placed Robot with PAPER to factory", + "[015] [18:47:59 UTC] Viper placed Scientist with SCISSORS to university", + "[015] [18:47:59 UTC] Viper placed Artist with ROCK to theatre", + "[015] [18:48:00 UTC] Ghost placed Politician with SCISSORS to university", + "[015] [18:48:01 UTC] Ghost placed Robot with ROCK to dump", + "[015] [18:48:01 UTC] Ghost placed Scientist with PAPER to theatre", + "[015] [18:48:02 UTC] Ghost placed Artist with SCISSORS to square", + "[015] [18:48:02 UTC] Viper (p2) ready", + "[015] [18:48:03 UTC] Ghost (p3) ready" ], "transactions": [], "messages": [ @@ -472,15 +2311,15 @@ "sender": "Ghost", "avatar": "/avatars/ghost.png", "content": "Hello world!", - "timestamp": 1769956383777 + "timestamp": 1770144465977 }, { "sender": "Viper", "avatar": "/avatars/viper.png", "content": "Hello world!", - "timestamp": 1769956388885 + "timestamp": 1770144472157 } ], - "startTime": 1769956400405 + "startTime": 1770144473674 } ] \ No newline at end of file diff --git a/frontend/lib/logUtils.ts b/frontend/lib/logUtils.ts new file mode 100644 index 0000000..460b206 --- /dev/null +++ b/frontend/lib/logUtils.ts @@ -0,0 +1,5 @@ +export const formatLog = (gameId: string, message: string) => { + const now = new Date(); + const timeStr = now.toISOString().split('T')[1].split('.')[0] + ' UTC'; + return `[${gameId}] [${timeStr}] ${message}`; +}; diff --git a/frontend/lib/types.ts b/frontend/lib/types.ts index 323a79b..6d1605b 100644 --- a/frontend/lib/types.ts +++ b/frontend/lib/types.ts @@ -23,8 +23,9 @@ export interface GameTransaction { export interface Game { id: string; // Game Hash + displayId?: string; // Sequential ID (e.g. 001) roomId: string; // Readable name - status: 'waiting' | 'starting' | 'playing' | 'finished'; + status: 'waiting' | 'playing' | 'finished'; isPrivate: boolean; createdAt: number; players: Player[]; diff --git a/frontend/next.config.js b/frontend/next.config.js index 658404a..59e4d5c 100644 --- a/frontend/next.config.js +++ b/frontend/next.config.js @@ -1,4 +1,17 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + webpack: (config) => { + config.resolve.fallback = { + ...config.resolve.fallback, + "fs": false, + "encoding": false, + "os": false, + "path": false, + "worker_threads": false, + "crypto": false + }; + return config; + } +}; module.exports = nextConfig; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index af47837..cdb49f3 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,6 +11,7 @@ "@rainbow-me/rainbowkit": "^2.0.0", "@types/uuid": "^10.0.0", "clsx": "^2.1.0", + "face-api.js": "^0.22.2", "framer-motion": "^11.0.0", "lucide-react": "^0.330.0", "next": "14.1.0", @@ -3843,6 +3844,32 @@ "react": "^18 || ^19" } }, + "node_modules/@tensorflow/tfjs-core": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-1.7.0.tgz", + "integrity": "sha512-uwQdiklNjqBnHPeseOdG0sGxrI3+d6lybaKu2+ou3ajVeKdPEwpWbgqA6iHjq1iylnOGkgkbbnQ6r2lwkiIIHw==", + "license": "Apache-2.0", + "dependencies": { + "@types/offscreencanvas": "~2019.3.0", + "@types/seedrandom": "2.4.27", + "@types/webgl-ext": "0.0.30", + "@types/webgl2": "0.0.4", + "node-fetch": "~2.1.2", + "seedrandom": "2.4.3" + }, + "engines": { + "yarn": ">= 1.3.2" + } + }, + "node_modules/@tensorflow/tfjs-core/node_modules/node-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", + "integrity": "sha512-IHLHYskTc2arMYsHZH82PVX8CSKT5lzb7AXeyO06QnjGDKtkv+pv3mEki6S7reB/x1QPo+YPxQRNEVgR5V/w3Q==", + "license": "MIT", + "engines": { + "node": "4.x || >=6.0.0" + } + }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -3882,6 +3909,12 @@ "undici-types": "~6.21.0" } }, + "node_modules/@types/offscreencanvas": { + "version": "2019.3.0", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz", + "integrity": "sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==", + "license": "MIT" + }, "node_modules/@types/prop-types": { "version": "15.7.15", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", @@ -3911,6 +3944,12 @@ "@types/react": "^18.0.0" } }, + "node_modules/@types/seedrandom": { + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.27.tgz", + "integrity": "sha512-YvMLqFak/7rt//lPBtEHv3M4sRNA+HGxrhFZ+DQs9K2IkYJbNwVIb8avtJfhDiuaUBX/AW0jnjv48FV8h3u9bQ==", + "license": "MIT" + }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -3923,6 +3962,18 @@ "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", "license": "MIT" }, + "node_modules/@types/webgl-ext": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/webgl-ext/-/webgl-ext-0.0.30.tgz", + "integrity": "sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg==", + "license": "MIT" + }, + "node_modules/@types/webgl2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.4.tgz", + "integrity": "sha512-PACt1xdErJbMUOUweSrbVM7gSIYm1vTncW2hF6Os/EeWi6TXYAYMPp+8v6rzHmypE5gHrxaxZNXgMkJVIdZpHw==", + "license": "MIT" + }, "node_modules/@types/ws": { "version": "7.4.7", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", @@ -6820,6 +6871,22 @@ "node": "> 0.1.90" } }, + "node_modules/face-api.js": { + "version": "0.22.2", + "resolved": "https://registry.npmjs.org/face-api.js/-/face-api.js-0.22.2.tgz", + "integrity": "sha512-9Bbv/yaBRTKCXjiDqzryeKhYxmgSjJ7ukvOvEBy6krA0Ah/vNBlsf7iBNfJljWiPA8Tys1/MnB3lyP2Hfmsuyw==", + "license": "MIT", + "dependencies": { + "@tensorflow/tfjs-core": "1.7.0", + "tslib": "^1.11.1" + } + }, + "node_modules/face-api.js/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -8920,6 +8987,12 @@ "loose-envify": "^1.1.0" } }, + "node_modules/seedrandom": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.3.tgz", + "integrity": "sha512-2CkZ9Wn2dS4mMUWQaXLsOAfGD+irMlLEeSP3cMxpGbgyOOzJGFa+MWCOMTOCMyZinHRPxyOj/S/C57li/1to6Q==", + "license": "MIT" + }, "node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", diff --git a/frontend/package.json b/frontend/package.json index 1458547..22d61f9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,6 +12,7 @@ "@rainbow-me/rainbowkit": "^2.0.0", "@types/uuid": "^10.0.0", "clsx": "^2.1.0", + "face-api.js": "^0.22.2", "framer-motion": "^11.0.0", "lucide-react": "^0.330.0", "next": "14.1.0", diff --git a/frontend/public/Locations closeups/Dump.png b/frontend/public/Locations closeups/Dump.png new file mode 100644 index 0000000..605ad63 Binary files /dev/null and b/frontend/public/Locations closeups/Dump.png differ diff --git a/frontend/public/Locations closeups/Energy station.png b/frontend/public/Locations closeups/Energy station.png new file mode 100644 index 0000000..b780e0a Binary files /dev/null and b/frontend/public/Locations closeups/Energy station.png differ diff --git a/frontend/public/Locations closeups/Factory.png b/frontend/public/Locations closeups/Factory.png new file mode 100644 index 0000000..210f7f9 Binary files /dev/null and b/frontend/public/Locations closeups/Factory.png differ diff --git a/frontend/public/Locations closeups/Square.png b/frontend/public/Locations closeups/Square.png new file mode 100644 index 0000000..fc42273 Binary files /dev/null and b/frontend/public/Locations closeups/Square.png differ diff --git a/frontend/public/Locations closeups/Teatre.png b/frontend/public/Locations closeups/Teatre.png new file mode 100644 index 0000000..64ecb0e Binary files /dev/null and b/frontend/public/Locations closeups/Teatre.png differ diff --git a/frontend/public/Locations closeups/University.png b/frontend/public/Locations closeups/University.png new file mode 100644 index 0000000..db8266b Binary files /dev/null and b/frontend/public/Locations closeups/University.png differ diff --git a/frontend/public/actions/Blackout.png b/frontend/public/actions/Blackout.png new file mode 100644 index 0000000..27d7849 Binary files /dev/null and b/frontend/public/actions/Blackout.png differ diff --git a/frontend/public/actions/Change rsource.png b/frontend/public/actions/Change rsource.png new file mode 100644 index 0000000..21baa67 Binary files /dev/null and b/frontend/public/actions/Change rsource.png differ diff --git a/frontend/public/actions/Charity.png b/frontend/public/actions/Charity.png new file mode 100644 index 0000000..0403ff5 Binary files /dev/null and b/frontend/public/actions/Charity.png differ diff --git a/frontend/public/actions/Sabotage.png b/frontend/public/actions/Sabotage.png new file mode 100644 index 0000000..66d7a07 Binary files /dev/null and b/frontend/public/actions/Sabotage.png differ diff --git a/frontend/public/actions/Student strikes.png b/frontend/public/actions/Student strikes.png new file mode 100644 index 0000000..39f9332 Binary files /dev/null and b/frontend/public/actions/Student strikes.png differ diff --git a/frontend/public/actions/Teleport.png b/frontend/public/actions/Teleport.png new file mode 100644 index 0000000..bca3577 Binary files /dev/null and b/frontend/public/actions/Teleport.png differ diff --git a/frontend/public/actions/Under construction.png b/frontend/public/actions/Under construction.png new file mode 100644 index 0000000..2265af0 Binary files /dev/null and b/frontend/public/actions/Under construction.png differ diff --git a/frontend/public/actions/action_card_exchange.png b/frontend/public/actions/action_card_exchange.png deleted file mode 100644 index b90b430..0000000 Binary files a/frontend/public/actions/action_card_exchange.png and /dev/null differ diff --git a/frontend/public/actions/action_card_upgrade.png b/frontend/public/actions/action_card_upgrade.png deleted file mode 100644 index 9e030d5..0000000 Binary files a/frontend/public/actions/action_card_upgrade.png and /dev/null differ diff --git a/frontend/public/actions/action_mat_cyber_spy.jpg b/frontend/public/actions/action_mat_cyber_spy.jpg deleted file mode 100644 index 28a6a57..0000000 Binary files a/frontend/public/actions/action_mat_cyber_spy.jpg and /dev/null differ diff --git a/frontend/public/actions/action_mat_overgrowth.png b/frontend/public/actions/action_mat_overgrowth.png deleted file mode 100644 index da1a91b..0000000 Binary files a/frontend/public/actions/action_mat_overgrowth.png and /dev/null differ diff --git a/frontend/public/actions/action_mat_red_monolith.png b/frontend/public/actions/action_mat_red_monolith.png deleted file mode 100644 index 7f446f3..0000000 Binary files a/frontend/public/actions/action_mat_red_monolith.png and /dev/null differ diff --git a/frontend/public/actions/action_nonmat_council.png b/frontend/public/actions/action_nonmat_council.png deleted file mode 100644 index beeccc1..0000000 Binary files a/frontend/public/actions/action_nonmat_council.png and /dev/null differ diff --git a/frontend/public/actions/action_nonmat_priestess.png b/frontend/public/actions/action_nonmat_priestess.png deleted file mode 100644 index 02cfcf1..0000000 Binary files a/frontend/public/actions/action_nonmat_priestess.png and /dev/null differ diff --git a/frontend/public/actions/action_nonmat_sky_city.png b/frontend/public/actions/action_nonmat_sky_city.png deleted file mode 100644 index 95fb285..0000000 Binary files a/frontend/public/actions/action_nonmat_sky_city.png and /dev/null differ diff --git a/frontend/public/actions/eco.png b/frontend/public/actions/eco.png new file mode 100644 index 0000000..5db89dc Binary files /dev/null and b/frontend/public/actions/eco.png differ diff --git a/frontend/public/actors/Artist.png b/frontend/public/actors/Artist.png new file mode 100644 index 0000000..b28dadb Binary files /dev/null and b/frontend/public/actors/Artist.png differ diff --git a/frontend/public/actors/Polotican.png b/frontend/public/actors/Polotican.png new file mode 100644 index 0000000..47fd121 Binary files /dev/null and b/frontend/public/actors/Polotican.png differ diff --git a/frontend/public/actors/Robot.png b/frontend/public/actors/Robot.png new file mode 100644 index 0000000..c29e4a6 Binary files /dev/null and b/frontend/public/actors/Robot.png differ diff --git a/frontend/public/actors/Scientist.png b/frontend/public/actors/Scientist.png new file mode 100644 index 0000000..f1b034c Binary files /dev/null and b/frontend/public/actors/Scientist.png differ diff --git a/frontend/public/actors/actor_artist.png b/frontend/public/actors/actor_artist.png deleted file mode 100644 index 662dd1b..0000000 Binary files a/frontend/public/actors/actor_artist.png and /dev/null differ diff --git a/frontend/public/actors/actor_politician.png b/frontend/public/actors/actor_politician.png deleted file mode 100644 index 9c38ac7..0000000 Binary files a/frontend/public/actors/actor_politician.png and /dev/null differ diff --git a/frontend/public/actors/actor_robot.png b/frontend/public/actors/actor_robot.png deleted file mode 100644 index 6a42c58..0000000 Binary files a/frontend/public/actors/actor_robot.png and /dev/null differ diff --git a/frontend/public/actors/actor_scientist.png b/frontend/public/actors/actor_scientist.png deleted file mode 100644 index aada7d2..0000000 Binary files a/frontend/public/actors/actor_scientist.png and /dev/null differ diff --git a/frontend/public/actors/commander_lady.png b/frontend/public/actors/commander_lady.png deleted file mode 100644 index c44be48..0000000 Binary files a/frontend/public/actors/commander_lady.png and /dev/null differ diff --git a/frontend/public/actors/mask_lady.png b/frontend/public/actors/mask_lady.png deleted file mode 100644 index 15f810c..0000000 Binary files a/frontend/public/actors/mask_lady.png and /dev/null differ diff --git a/frontend/public/actors/robot_ring.png b/frontend/public/actors/robot_ring.png deleted file mode 100644 index 0cc6870..0000000 Binary files a/frontend/public/actors/robot_ring.png and /dev/null differ diff --git a/frontend/public/actors/tech_guy.png b/frontend/public/actors/tech_guy.png deleted file mode 100644 index 1038873..0000000 Binary files a/frontend/public/actors/tech_guy.png and /dev/null differ diff --git a/frontend/public/intangibles/resource_culture.png b/frontend/public/intangibles/resource_Art.png similarity index 100% rename from frontend/public/intangibles/resource_culture.png rename to frontend/public/intangibles/resource_Art.png diff --git a/frontend/public/intangibles/resource_victory.png b/frontend/public/intangibles/resource_Glory.png similarity index 100% rename from frontend/public/intangibles/resource_victory.png rename to frontend/public/intangibles/resource_Glory.png diff --git a/frontend/public/intangibles/resource_fame.png b/frontend/public/intangibles/resource_VP.png similarity index 100% rename from frontend/public/intangibles/resource_fame.png rename to frontend/public/intangibles/resource_VP.png diff --git a/frontend/public/intangibles/resource_focus.png b/frontend/public/intangibles/resource_power.png similarity index 100% rename from frontend/public/intangibles/resource_focus.png rename to frontend/public/intangibles/resource_power.png diff --git a/frontend/public/intangibles/resource_ledger.png b/frontend/public/intangibles/resource_wisdom.png similarity index 100% rename from frontend/public/intangibles/resource_ledger.png rename to frontend/public/intangibles/resource_wisdom.png diff --git a/frontend/public/map/game_map_detail.jpg b/frontend/public/map/game_map_detail.jpg deleted file mode 100644 index d185f95..0000000 Binary files a/frontend/public/map/game_map_detail.jpg and /dev/null differ diff --git a/frontend/public/map/game_map_main.jpg b/frontend/public/map/game_map_main.jpg deleted file mode 100644 index 4965723..0000000 Binary files a/frontend/public/map/game_map_main.jpg and /dev/null differ diff --git a/frontend/public/map/map_board_detail.jpg b/frontend/public/map/map_board_detail.jpg deleted file mode 100644 index d185f95..0000000 Binary files a/frontend/public/map/map_board_detail.jpg and /dev/null differ diff --git a/frontend/public/map/map_board_main.jpg b/frontend/public/map/map_board_main.jpg deleted file mode 100644 index 4965723..0000000 Binary files a/frontend/public/map/map_board_main.jpg and /dev/null differ diff --git a/frontend/public/models/tiny_face_detector_model-shard1 b/frontend/public/models/tiny_face_detector_model-shard1 new file mode 100644 index 0000000..a3f113a Binary files /dev/null and b/frontend/public/models/tiny_face_detector_model-shard1 differ diff --git a/frontend/public/models/tiny_face_detector_model-weights_manifest.json b/frontend/public/models/tiny_face_detector_model-weights_manifest.json new file mode 100644 index 0000000..7d3b222 --- /dev/null +++ b/frontend/public/models/tiny_face_detector_model-weights_manifest.json @@ -0,0 +1 @@ +[{"weights":[{"name":"conv0/filters","shape":[3,3,3,16],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009007044399485869,"min":-1.2069439495311063}},{"name":"conv0/bias","shape":[16],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005263455241334205,"min":-0.9211046672334858}},{"name":"conv1/depthwise_filter","shape":[3,3,16,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004001977630690033,"min":-0.5042491814669441}},{"name":"conv1/pointwise_filter","shape":[1,1,16,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013836609615999109,"min":-1.411334180831909}},{"name":"conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0015159862590771096,"min":-0.30926119685173037}},{"name":"conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002666276225856706,"min":-0.317286870876948}},{"name":"conv2/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015265831292844286,"min":-1.6792414422128714}},{"name":"conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0020280554598453,"min":-0.37113414915168985}},{"name":"conv3/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006100742489683862,"min":-0.8907084034938438}},{"name":"conv3/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.016276211832083907,"min":-2.0508026908425725}},{"name":"conv3/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003394414279975143,"min":-0.7637432129944072}},{"name":"conv4/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006716050119961009,"min":-0.8059260143953211}},{"name":"conv4/pointwise_filter","shape":[1,1,128,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.021875603993733724,"min":-2.8875797271728514}},{"name":"conv4/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0041141652009066415,"min":-0.8187188749804216}},{"name":"conv5/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008423839597141042,"min":-0.9013508368940915}},{"name":"conv5/pointwise_filter","shape":[1,1,256,512],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.030007277283014035,"min":-3.8709387695088107}},{"name":"conv5/bias","shape":[512],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008402082966823203,"min":-1.4871686851277068}},{"name":"conv8/filters","shape":[1,1,512,25],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.028336129469030042,"min":-4.675461362389957}},{"name":"conv8/bias","shape":[25],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002268134028303857,"min":-0.41053225912299807}}],"paths":["tiny_face_detector_model-shard1"]}] \ No newline at end of file diff --git a/frontend/public/resources/resource_bio.png b/frontend/public/resources/resource_Recycle.png similarity index 100% rename from frontend/public/resources/resource_bio.png rename to frontend/public/resources/resource_Recycle.png diff --git a/frontend/public/resources/resource_box.png b/frontend/public/resources/resource_product.png similarity index 100% rename from frontend/public/resources/resource_box.png rename to frontend/public/resources/resource_product.png