faaizashiq commited on
Commit
60b1e7f
Β·
verified Β·
1 Parent(s): fcd6530

Update backend/agents/puzzle_agent.py

Browse files
Files changed (1) hide show
  1. backend/agents/puzzle_agent.py +30 -9
backend/agents/puzzle_agent.py CHANGED
@@ -304,7 +304,7 @@ STRICT RULES:
304
  2. Reference the exact mission steps for that level in its goal_description.
305
  3. CRITICAL: Provide a UNIQUE programming/logic problem in the `story` field for EACH level.
306
  4. The `title` of each level should match its assigned Theme (e.g., "Bank Heist", "Space Station").
307
- 5. Generate a SPECIFIC `hint` for each level that actually helps them solve the logical problem. Do NOT use generic hints like "look closely".
308
 
309
  OUTPUT only valid JSON (no markdown):
310
  {{
@@ -319,6 +319,9 @@ OUTPUT only valid JSON (no markdown):
319
  "story": "Present the unique logical problem or scenario for this level here...",
320
  "goal_description": "Step 1: [action] β†’ Step 2: [action] β†’ Reach Exit",
321
  "hint": "Specific, highly useful hint for this specific puzzle logic",
 
 
 
322
  "allowed_blocks": ["move_forward", "turn_left", "turn_right"]
323
  }}
324
  ]
@@ -356,16 +359,21 @@ OUTPUT only valid JSON (no markdown):
356
  }
357
  diff_key = _diff_norm.get(difficulty.lower(), "easy")
358
 
359
- # Step 1: Pick 5 distinct scenarios matching normalised difficulty
360
  filtered = [s for s in self.scenarios if s.get("difficulty", "").lower() == diff_key]
361
- if not filtered:
 
362
  filtered = self.scenarios
363
 
364
- # Try to get 5 distinct scenarios, allow duplicates if dataset is too small
365
- arc_scenarios = []
366
- for _ in range(5):
367
  arc_scenarios.append(random.choice(filtered) if filtered else {})
368
 
 
 
 
 
369
  # Step 2: Pick DAA concept β€” harder = more complex maze type + larger dim
370
  concept_map = {
371
  "easy": [DAA_CONCEPTS[0], DAA_CONCEPTS[3]], # collect+reach, sequence
@@ -400,7 +408,7 @@ OUTPUT only valid JSON (no markdown):
400
  print(f"[PuzzleAgent] AI enrichment failed: {e}. Using fallback.")
401
  arc = self._build_fallback_arc(arc_scenarios, concept, compiled_grids)
402
 
403
- # Step 5: Inject compiled grids into each level
404
  levels = arc.get("levels", [])
405
  for i, level in enumerate(levels):
406
  cg = compiled_grids[i] if i < len(compiled_grids) else compiled_grids[-1]
@@ -408,13 +416,23 @@ OUTPUT only valid JSON (no markdown):
408
  level["maze_rows"] = cg["rows"]
409
  level["maze_cols"] = cg["cols"]
410
  level["ordered_steps"] = cg["ordered_steps"]
411
- level["theme_palette"] = cg["palette"]
 
 
 
 
 
 
 
 
 
 
412
  level["daa_concept"] = concept["title"]
413
  level["daa_description"]= concept["description"]
414
  level["type"] = "maze"
415
 
416
  arc["levels"] = levels
417
- arc["theme_palette"] = compiled_grids[0]["palette"]
418
  return arc
419
 
420
  # ─────────────────────────────────────────────────────────
@@ -438,6 +456,9 @@ OUTPUT only valid JSON (no markdown):
438
  ),
439
  "goal_description": step_str + " β†’ Exit",
440
  "hint": "Try planning your path by starting from the end and tracing backwards.",
 
 
 
441
  "daa_concept": concept["title"],
442
  "daa_description": concept["description"],
443
  "allowed_blocks": ["move_forward", "turn_left", "turn_right"],
 
304
  2. Reference the exact mission steps for that level in its goal_description.
305
  3. CRITICAL: Provide a UNIQUE programming/logic problem in the `story` field for EACH level.
306
  4. The `title` of each level should match its assigned Theme (e.g., "Bank Heist", "Space Station").
307
+ 5. CRITICAL: Generate a COMPLETELY UNIQUE `hint` for EVERY level. The hint MUST be different for Level 1, Level 2, etc., and must directly reference the specific theme/logic of that exact level! Do NOT repeat hints!
308
 
309
  OUTPUT only valid JSON (no markdown):
310
  {{
 
319
  "story": "Present the unique logical problem or scenario for this level here...",
320
  "goal_description": "Step 1: [action] β†’ Step 2: [action] β†’ Reach Exit",
321
  "hint": "Specific, highly useful hint for this specific puzzle logic",
322
+ "npc_emoji": "🏦",
323
+ "item_emoji": "πŸ’΅",
324
+ "goal_emoji": "🏁",
325
  "allowed_blocks": ["move_forward", "turn_left", "turn_right"]
326
  }}
327
  ]
 
359
  }
360
  diff_key = _diff_norm.get(difficulty.lower(), "easy")
361
 
362
+ # Step 1: Pick 5 completely DISTINCT scenarios matching normalised difficulty
363
  filtered = [s for s in self.scenarios if s.get("difficulty", "").lower() == diff_key]
364
+ if len(filtered) < 5:
365
+ # If not enough filtered, use the entire dataset to guarantee 5 unique scenarios
366
  filtered = self.scenarios
367
 
368
+ arc_scenarios = random.sample(filtered, min(5, len(filtered)))
369
+ # Fallback if dataset has less than 5 elements
370
+ while len(arc_scenarios) < 5:
371
  arc_scenarios.append(random.choice(filtered) if filtered else {})
372
 
373
+ # Ensure each level gets a distinct visual theme color palette
374
+ palette_keys = list(THEME_PALETTES.keys())
375
+ random.shuffle(palette_keys)
376
+
377
  # Step 2: Pick DAA concept β€” harder = more complex maze type + larger dim
378
  concept_map = {
379
  "easy": [DAA_CONCEPTS[0], DAA_CONCEPTS[3]], # collect+reach, sequence
 
408
  print(f"[PuzzleAgent] AI enrichment failed: {e}. Using fallback.")
409
  arc = self._build_fallback_arc(arc_scenarios, concept, compiled_grids)
410
 
411
+ # Step 5: Inject compiled grids and dynamic palettes into each level
412
  levels = arc.get("levels", [])
413
  for i, level in enumerate(levels):
414
  cg = compiled_grids[i] if i < len(compiled_grids) else compiled_grids[-1]
 
416
  level["maze_rows"] = cg["rows"]
417
  level["maze_cols"] = cg["cols"]
418
  level["ordered_steps"] = cg["ordered_steps"]
419
+
420
+ # Assign a distinct color palette
421
+ palette_key = palette_keys[i % len(palette_keys)]
422
+ base_palette = THEME_PALETTES.get(palette_key, THEME_PALETTES["default"]).copy()
423
+
424
+ # Inject dynamic AI emojis into the palette so the Flutter UI can read them
425
+ base_palette["npc_emoji"] = level.get("npc_emoji", "🀡")
426
+ base_palette["item_emoji"] = level.get("item_emoji", "πŸ”‘")
427
+ base_palette["goal_emoji"] = level.get("goal_emoji", "πŸš€")
428
+
429
+ level["theme_palette"] = base_palette
430
  level["daa_concept"] = concept["title"]
431
  level["daa_description"]= concept["description"]
432
  level["type"] = "maze"
433
 
434
  arc["levels"] = levels
435
+ # Remove top-level theme_palette so we don't override the distinct ones later
436
  return arc
437
 
438
  # ─────────────────────────────────────────────────────────
 
456
  ),
457
  "goal_description": step_str + " β†’ Exit",
458
  "hint": "Try planning your path by starting from the end and tracing backwards.",
459
+ "npc_emoji": "🀡",
460
+ "item_emoji": "πŸ”‘",
461
+ "goal_emoji": "πŸš€",
462
  "daa_concept": concept["title"],
463
  "daa_description": concept["description"],
464
  "allowed_blocks": ["move_forward", "turn_left", "turn_right"],