|
24 | 24 | DRAW_JS = """ |
25 | 25 | const ARENA = (function(){ |
26 | 26 | const PAL = ['#e5484d','#4593ff','#46a758','#f5d90a','#8e4ec6','#f76b15','#e93d82','#12a594']; |
27 | | - const BG = '#0d1117', GRID_LINE = 'rgba(255,255,255,0.05)'; |
| 27 | + const BG = '#0d1117', GRID_LINE = 'rgba(255,255,255,0.05)', ROCK_COL = '#4b5563'; |
28 | 28 | let W, H, CELL; |
29 | 29 | function col(i){ return PAL[i % PAL.length]; } |
30 | 30 | function setup(cv, G){ |
|
38 | 38 | ctx.strokeStyle = GRID_LINE; ctx.lineWidth = 1; |
39 | 39 | for(let x=0;x<=W;x++){ ctx.beginPath(); ctx.moveTo(x*CELL,0); ctx.lineTo(x*CELL,cv.height); ctx.stroke(); } |
40 | 40 | for(let y=0;y<=H;y++){ ctx.beginPath(); ctx.moveTo(0,y*CELL); ctx.lineTo(cv.width,y*CELL); ctx.stroke(); } |
| 41 | + // static rock obstacles |
| 42 | + ctx.fillStyle = ROCK_COL; |
| 43 | + (G.rocks || []).forEach(r => ctx.fillRect(r[0]*CELL, r[1]*CELL, CELL, CELL)); |
41 | 44 | const n = (G.frames[0].heads || []).length; |
42 | 45 | // rebuild trails by accumulating every head cell up to frame i |
43 | 46 | for(let p=0;p<n;p++){ |
@@ -118,7 +121,12 @@ def parse(self, raw: bytes, players: list[dict] | None = None) -> ReplayData: |
118 | 121 | frames=frames, |
119 | 122 | winner=winner, |
120 | 123 | draw=draw, |
121 | | - extra={"names": names, "num_players": n, "max_ticks": log.get("max_ticks")}, |
| 124 | + extra={ |
| 125 | + "names": names, |
| 126 | + "num_players": n, |
| 127 | + "max_ticks": log.get("max_ticks"), |
| 128 | + "rocks": log.get("rocks", []), |
| 129 | + }, |
122 | 130 | ) |
123 | 131 |
|
124 | 132 | def peek_winner(self, raw: bytes, players: list[dict] | None = None) -> tuple[str | None, bool] | None: |
|
0 commit comments