Skip to content

Commit 195465f

Browse files
committed
avoid recursion in molecule flood fill
no change in overall performance, but avoids the possibility of stack overflow.
1 parent 72731b6 commit 195465f

File tree

2 files changed

+24
-20
lines changed

2 files changed

+24
-20
lines changed

sim.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -361,37 +361,40 @@ static void add_atom_to_molecule(struct board *board, struct molecule *molecule,
361361
molecule->atoms = realloc(molecule->atoms, molecule->capacity * sizeof(struct atom_ref_at_position));
362362
}
363363
molecule->atoms[molecule->size++] = a;
364-
365-
for (int bond_direction = 0; bond_direction < 6; ++bond_direction) {
366-
atom ab = (BOND_LOW_BITS & ~RECENT_BONDS) << bond_direction;
367-
if (!(*a.atom & ab))
368-
continue;
369-
struct vector d = u_offset_for_direction(bond_direction);
370-
struct vector p = { a.position.u + d.u, a.position.v + d.v };
371-
struct atom_ref_at_position b = { lookup_atom(board, p), p };
372-
373-
if (*b.atom & VISITED)
374-
continue;
375-
*b.atom |= VISITED;
376-
377-
int height = get_bond_height(board, a, ab);
378-
int opposite_direction = bond_direction + (bond_direction < 3 ? 3 : -3);
379-
atom ba = (BOND_LOW_BITS & ~RECENT_BONDS) << opposite_direction;
380-
b.atom = lookup_atom_at_height(board, b, ba, height);
381-
if (b.atom)
382-
add_atom_to_molecule(board, molecule, b);
383-
}
384364
}
385365

386366
// returns the molecule containing the given atom. accurate in the presence of arbitrary overlap.
387367
// movements don't need this, as overlapped atoms during movements cause collisions anyway.
388368
// TODO: use this for conduits too.
389369
static struct molecule *get_molecule(struct board *board, struct atom_ref_at_position a)
390370
{
371+
board->molecule.cursor = 0;
391372
board->molecule.size = 0;
392373
// VISITED goes on the bottommost atom of the hex even if it isn't part of the molecule
393374
*lookup_atom(board, a.position) |= VISITED;
394375
add_atom_to_molecule(board, &board->molecule, a);
376+
while (board->molecule.cursor < board->molecule.size) {
377+
a = board->molecule.atoms[board->molecule.cursor++];
378+
for (int bond_direction = 0; bond_direction < 6; ++bond_direction) {
379+
atom ab = (BOND_LOW_BITS & ~RECENT_BONDS) << bond_direction;
380+
if (!(*a.atom & ab))
381+
continue;
382+
struct vector d = u_offset_for_direction(bond_direction);
383+
struct vector p = { a.position.u + d.u, a.position.v + d.v };
384+
struct atom_ref_at_position b = { lookup_atom(board, p), p };
385+
386+
if (*b.atom & VISITED)
387+
continue;
388+
*b.atom |= VISITED;
389+
390+
int height = get_bond_height(board, a, ab);
391+
int opposite_direction = bond_direction + (bond_direction < 3 ? 3 : -3);
392+
atom ba = (BOND_LOW_BITS & ~RECENT_BONDS) << opposite_direction;
393+
b.atom = lookup_atom_at_height(board, b, ba, height);
394+
if (b.atom)
395+
add_atom_to_molecule(board, &board->molecule, b);
396+
}
397+
}
395398
for (uint32_t i = 0; i < board->molecule.size; ++i)
396399
*lookup_atom(board, board->molecule.atoms[i].position) &= ~VISITED;
397400
return &board->molecule;

sim.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ struct conduit {
237237

238238
struct molecule {
239239
struct atom_ref_at_position *atoms;
240+
size_t cursor;
240241
size_t size;
241242
size_t capacity;
242243
};

0 commit comments

Comments
 (0)