Show code
<think>
Okay, let's see. I need to create an HTML file that simulates 60 people leaving a room through an exit. The grid is 40x30 cells, and each step, everyone moves towards the exit based on a distance field. They can't enter occupied cells, so congestion forms. The output has to be self-contained, under 120 lines, and use requestAnimationFrame. Alright.
First, structure the HTML. The canvas tag with some width and height, but since it's a grid of 40x30, maybe set it to 800x600 pixels (20px per cell) for visibility. But the user said the grid is 40x30 cells. Hmm, so the cells can be 20x20 each. Wait, but the user might not specify pixel size. Maybe just set the canvas to 40x30 cells but scaled up. Wait, better to make sure each cell is a pixel? No, because then it would be very small. Maybe 20px per cell, so canvas is 800x600.
Wait, but the user says "cell grid drawn on a canvas". The exact pixel size isn't specified, so perhaps I can choose a reasonable size. Let's go with 40 cells wide, 30 tall. So maybe 400x300 pixels, each cell 10x10. That's manageable. So the canvas element would have width 400 and height 300, with a 10px per cell scaling.
Now the main elements: the canvas, and some text to show the step count and how many have exited.
The simulation needs a grid. Each cell has a distance to the exit. The exit is probably at the bottom right, but need to set it as a specific cell. Let's say the exit is at (39,29), the bottom-right corner. Wait, indexes start at 0, so maybe exit is at (39,29).
The distance field is precomputed. So first, compute for each cell (x,y) the distance to the exit, but moving step by step. Wait, but distance field can be computed as BFS from the exit. So the distance for each cell is the minimum steps needed to reach the exit, considering walls or not? Since it's a room, maybe the grid is all open except the exit is the target. Wait, the problem says "one exit", so the exit is just a single cell which people can leave from.
Wait, perhaps the exit is a door at the right side, but the user says 'one exit', so maybe the exit is a specific cell, and when people reach it, they leave. So the distance field is computed as the shortest path from each cell to the exit. So the distance field would be a 2D array where each cell's value is the steps needed to reach the exit. We can compute this using BFS.
So first step: set up the grid. The canvas size is 40x30 cells. The exit is at (39,29) (since it's 0-based). Wait, but maybe the exit is at the bottom-right corner, so that people have to move towards it. Alternatively, maybe the exit is on a wall, but the exit cell is the last before leaving. Hmm, perhaps the exit is at the end of the grid, so that the distance field is computed as the minimal steps to reach that point.
So first, create the distance field. Initialize a 2D array (40x30) with all values as undefined or infinity. Then set the exit cell's distance to 0. Then perform BFS to propagate the distances.
Wait, the BFS approach would be:
Initialize the exit cell's distance to 0. Then, for each cell in the queue, look at its neighbors and set their distance to current distance +1, if not set yet. Proceed until all cells are filled.
Yes. So the distance field is computed once at the start.
Then, the people are placed randomly in the grid, except the exit cell and maybe adjacent cells.
Wait, the initial positions need to be on cells that are not the exit. Also, each person is on a different cell, so when placing 60 people, we need to make sure they don't start on the same cell. Let's think: 40x30 is 1200 cells. 60 is small, so randomly placing them is okay.
Each step:
For each person, determine the direction towards the exit based on the distance field. The direction is the direction to the neighbor cell (up, down, left, right) which has the smallest distance. But since the distance field is precomputed, each cell has its best direction.
Wait, the direction is the direction towards the exit, so for a cell (x,y), the next cell is the one among its four neighbors (if exist) that has the smallest distance. If multiple have the same distance, can choose one direction? Or maybe pick the first one.
Wait, the distance field is such that each cell's distance is exactly one more than the next cell. So the direction to move is to the neighbor cell with distance exactly one less. So for each cell, there should be exactly one direction (or maybe multiple) that gives the next step.
Wait, actually, the distance field would have for each cell, the distance is 1 + min of neighbors. So each cell has a unique path to the exit? Not necessarily, but the direction can be any direction that reduces the distance. Hmm. To make it deterministic, perhaps for each cell, there is a preferred direction (like the right direction first, then down, etc.)?
Alternatively, for each cell, the direction is the direction towards the neighbor with the smallest distance. Since the distance field is such that each cell's distance is exactly one less than the previous, so you can choose any adjacent cell with distance = current distance - 1. So for movement, each person can look at all four adjacent cells, and pick the one with the smallest distance (which should be exactly one less). Among those, perhaps choose the direction that's closest to the target.
Alternatively, to make it simple, for each cell, the direction can be determined by comparing the four neighbors and choosing the direction with the smallest distance. Let's code that.
So for a person at (x,y), the next cell is the direction with distance equal to distance[y][x] - 1. So check all four directions. For each direction (dx, dy), check if the next cell's distance is one less. Then pick one direction (maybe the first one found? Or the direction that's towards the exit's general direction?)
Alternatively, in code, for each direction in order of priority (like right, down, left, up), and pick the first direction towards a cell with distance one less.
Hmm, perhaps to keep it simple, for each direction in order of priority (maybe right, down, left, up?), and then pick the first direction that leads closer.
Alternatively, we can precompute for each cell the direction (dx, dy) that leads to the next step. For each cell, store the direction to move. This would be more efficient.
Yes, maybe during the BFS, when computing the distance, we can also store the direction to move for each cell. So when building the distance field, for each cell, when we set its distance from a neighbor, we can note the direction from the neighbor. Wait, maybe not. Alternatively, for each cell, once the distance is known, the direction can be