yxc20098 commited on
Commit
b08ad0f
·
1 Parent(s): bda094b

Phase 2: Play tab — larger minimap + bigger coordinate labels

Browse files

From play-testing feedback: the minimap was too small and the grid
coordinate numbers too small to read.

- Minimap moved to its own full-width row (was sharing a row at half
width with the briefing) and the gr.Image height raised 420 -> 620.
- Upscale raised 3x -> 5x (_PLAY_UPSCALE) for a crisp large display.
- Coordinate labels now use a real 34px TrueType font with a 3px
black outline (bright yellow fill) instead of PIL's tiny default
bitmap font — readable over any terrain.
- Click-to-cell math and grid spacing track _PLAY_UPSCALE.

Files changed (1) hide show
  1. app.py +54 -22
app.py CHANGED
@@ -1033,6 +1033,29 @@ Then run `evaluate.py --agent custom` with your agent integrated.
1033
  # human's run is scored by the identical rules as a model's.
1034
 
1035
  _PLAY_LEVELS = ["easy", "medium", "hard"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1036
 
1037
 
1038
  def _play_scenarios() -> list[str]:
@@ -1065,10 +1088,11 @@ def _md_escape(text: str) -> str:
1065
 
1066
 
1067
  def _play_minimap(render_state: dict):
1068
- """PIL minimap image — the same view an LLM agent is shown,
1069
- upscaled 3x (nearest-neighbour) so individual units stay distinct,
1070
- with a coordinate grid + axis labels every 10 cells so a human can
1071
- locate the cell coordinates the objective refers to."""
 
1072
  try:
1073
  import base64
1074
  import io
@@ -1082,27 +1106,35 @@ def _play_minimap(render_state: dict):
1082
  return None
1083
  img = Image.open(io.BytesIO(base64.b64decode(b64))).convert("RGB")
1084
  bw, bh = img.size
1085
- img = img.resize((bw * 3, bh * 3), Image.NEAREST)
 
1086
  iw, ih = img.size
1087
- cell_px = 18 # minimap CELL(6) * 3x upscale
1088
  rows = [r for r in (render_state.get("minimap") or "").split("\n")
1089
  if r]
1090
  cols = max((len(r) for r in rows), default=bw // 6)
1091
  nrows = len(rows) or bh // 6
1092
  draw = ImageDraw.Draw(img)
1093
- grid = (110, 112, 122)
1094
- label = (235, 235, 245)
 
1095
  step = 10
1096
  for cx in range(0, cols + 1, step):
1097
  x = min(iw - 1, cx * cell_px)
1098
- draw.line([(x, 0), (x, ih)], fill=grid, width=1)
1099
  if cx < cols:
1100
- draw.text((x + 2, 1), str(cx), fill=label)
 
 
 
1101
  for cy in range(0, nrows + 1, step):
1102
  y = min(ih - 1, cy * cell_px)
1103
- draw.line([(0, y), (iw, y)], fill=grid, width=1)
1104
  if cy < nrows:
1105
- draw.text((2, y + 1), str(cy), fill=label)
 
 
 
1106
  return img
1107
  except Exception: # noqa: BLE001
1108
  return None
@@ -1244,10 +1276,10 @@ def _play_click(sess, sel, queue, mode, evt: gr.SelectData):
1244
  )
1245
  h = len(rows)
1246
  w = max(len(r) for r in rows)
1247
- # _play_minimap renders at CELL(6) and upscales 3x the image
1248
- # the user clicks is w*18 x h*18 px; map the click back at that
1249
- # resolution, not the base CELL resolution.
1250
- img_w, img_h = w * 6 * 3, h * 6 * 3
1251
  cx, cy = minimap_click_to_cell(px, py, img_w, img_h, w, h)
1252
  note = f"🖱 Clicked cell **({cx}, {cy})**"
1253
  if mode == "Move here" and sel:
@@ -1513,12 +1545,12 @@ def build_app() -> gr.Blocks:
1513
  play_start = gr.Button("▶ Start", scale=1)
1514
  play_objective = gr.Markdown()
1515
  play_status = gr.Markdown(_play_status_md(None))
1516
- with gr.Row():
1517
- play_img = gr.Image(
1518
- label="Minimap — click to select units / give orders",
1519
- height=420, interactive=False, show_label=True,
1520
- )
1521
- play_brief = gr.Markdown()
1522
  play_units = gr.Dataframe(
1523
  label="Your units (✓ = selected)",
1524
  headers=["sel", "id", "type", "x", "y", "hp%",
 
1033
  # human's run is scored by the identical rules as a model's.
1034
 
1035
  _PLAY_LEVELS = ["easy", "medium", "hard"]
1036
+ _PLAY_UPSCALE = 5 # nearest-neighbour minimap upscale for the Play tab
1037
+
1038
+
1039
+ def _play_grid_font(size: int):
1040
+ """A large legible font for the minimap coordinate labels — tries
1041
+ real TrueType fonts, falls back to a scaled default."""
1042
+ from PIL import ImageFont
1043
+
1044
+ for path in (
1045
+ "/System/Library/Fonts/Supplemental/Arial Bold.ttf",
1046
+ "/System/Library/Fonts/Supplemental/Arial.ttf",
1047
+ "/System/Library/Fonts/Helvetica.ttc",
1048
+ "/Library/Fonts/Arial.ttf",
1049
+ "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
1050
+ ):
1051
+ try:
1052
+ return ImageFont.truetype(path, size)
1053
+ except Exception: # noqa: BLE001
1054
+ continue
1055
+ try:
1056
+ return ImageFont.load_default(size=size) # Pillow >= 10.1
1057
+ except Exception: # noqa: BLE001
1058
+ return ImageFont.load_default()
1059
 
1060
 
1061
  def _play_scenarios() -> list[str]:
 
1088
 
1089
 
1090
  def _play_minimap(render_state: dict):
1091
+ """PIL minimap image — the same view an LLM agent is shown, upscaled
1092
+ `_PLAY_UPSCALE`x (nearest-neighbour) so individual units stay
1093
+ distinct, with a coordinate grid + large outlined axis labels every
1094
+ 10 cells so a human can read off the cell coordinates the objective
1095
+ refers to."""
1096
  try:
1097
  import base64
1098
  import io
 
1106
  return None
1107
  img = Image.open(io.BytesIO(base64.b64decode(b64))).convert("RGB")
1108
  bw, bh = img.size
1109
+ scale = _PLAY_UPSCALE
1110
+ img = img.resize((bw * scale, bh * scale), Image.NEAREST)
1111
  iw, ih = img.size
1112
+ cell_px = 6 * scale # minimap CELL(6) * upscale
1113
  rows = [r for r in (render_state.get("minimap") or "").split("\n")
1114
  if r]
1115
  cols = max((len(r) for r in rows), default=bw // 6)
1116
  nrows = len(rows) or bh // 6
1117
  draw = ImageDraw.Draw(img)
1118
+ grid = (120, 123, 135)
1119
+ label = (255, 246, 120) # bright yellow, readable over terrain
1120
+ font = _play_grid_font(34)
1121
  step = 10
1122
  for cx in range(0, cols + 1, step):
1123
  x = min(iw - 1, cx * cell_px)
1124
+ draw.line([(x, 0), (x, ih)], fill=grid, width=2)
1125
  if cx < cols:
1126
+ draw.text(
1127
+ (x + 4, 2), str(cx), fill=label, font=font,
1128
+ stroke_width=3, stroke_fill=(0, 0, 0),
1129
+ )
1130
  for cy in range(0, nrows + 1, step):
1131
  y = min(ih - 1, cy * cell_px)
1132
+ draw.line([(0, y), (iw, y)], fill=grid, width=2)
1133
  if cy < nrows:
1134
+ draw.text(
1135
+ (4, y + 2), str(cy), fill=label, font=font,
1136
+ stroke_width=3, stroke_fill=(0, 0, 0),
1137
+ )
1138
  return img
1139
  except Exception: # noqa: BLE001
1140
  return None
 
1276
  )
1277
  h = len(rows)
1278
  w = max(len(r) for r in rows)
1279
+ # _play_minimap renders at CELL(6) and upscales _PLAY_UPSCALE x
1280
+ # map the click back at that resolution, not the base CELL one.
1281
+ img_w = w * 6 * _PLAY_UPSCALE
1282
+ img_h = h * 6 * _PLAY_UPSCALE
1283
  cx, cy = minimap_click_to_cell(px, py, img_w, img_h, w, h)
1284
  note = f"🖱 Clicked cell **({cx}, {cy})**"
1285
  if mode == "Move here" and sel:
 
1545
  play_start = gr.Button("▶ Start", scale=1)
1546
  play_objective = gr.Markdown()
1547
  play_status = gr.Markdown(_play_status_md(None))
1548
+ # Minimap on its own full-width row so it renders large.
1549
+ play_img = gr.Image(
1550
+ label="Minimap — click to select units / give orders",
1551
+ height=620, interactive=False, show_label=True,
1552
+ )
1553
+ play_brief = gr.Markdown()
1554
  play_units = gr.Dataframe(
1555
  label="Your units (✓ = selected)",
1556
  headers=["sel", "id", "type", "x", "y", "hp%",