This repository has been archived on 2025-03-20. You can view files and clone it, but cannot push or open issues or pull requests.
The-Powder-Toy/src/simulation
Tamás Bálint Misius b393050e55
Fix PHOT reflecting off thin walls of particles incorrectly
When PHOT fails to move (do_move or eval_move return "no move"), it looks for
a surface (a contour of boundaries, as reported by is_boundary) along its path
and reflects off (or refracts into, see below) it, using get_normal_interp to
find the point of incidence and get_normal to deduce the surface normal.
get_normal is given the point and angle of incidence, and attempts to traverse
the surface the point belongs to by running two "surface scout" processes.

These processes remember their own position and "heading", a subset of the
eight cardinal directions on the grid. They are initialized with the point of
incidence and a heading that includes all directions whose dot product with
the angle of incidence is non-negative (see direction_to_map). They then
perform a few iterations (SURF_RANGE).

In each iteration, the processes check all eight neighbours of the cell they
are on and select the first neighbouring cell they find that is both a
boundary (as reported by is_boundary) and that is within their heading. They
then move to this neighbouring cell and update their heading by discarding
directions that are not similar enough to (differ by more than 45 degrees
from) the one that took them where they are now (see find_next_boundary). If
they find no such neighbour, they stop.

Continuing the militaristic line of thinking introduced by the term "surface
scout", you can imagine the two processes as two paratroopers who arrive from
above, land on a horizontal surface, and one starts going left, while the
other starts going right. They initially expect the surface they land on to be
close to horizontal, but are also prepared for not too erratic changes in its
angle as they go. Changes too erratic (imagine a precipice) scare them and
force them to stop.

Once the processes finish, an imaginary line segment is drawn between the
cells they ended up on. If the line segment is long enough (estimated by j,
and compared against NORMAL_MIN_EST), get_normal returns a normal that is
perpendicular to it. If it is too short, get_normal gives up and returns
nothing (which results in the PHOT being killed).

This amounts to our paratroopers attempting to get the "lay of the land" by
walking away from where they landed and comparing where they end up. They also
know that if they are still relatively close to each other at the end of their
walk, their measurement is probably wrong and their mission should be aborted.

The bug this commit fixes is that get_normal returns bogus surface normals
when it encounters thin walls of particles, defined as walls exactly two
layers of particles thick. One-layer walls are not really walls, as movement
code allows particles to penetrate these, and three-layer and thicker walls
are too thick for the bug to manifest.

The bug manifests for two-layer walls because the "left" scout process is
drawn to the side of the wall opposite to the one with the point of incidence.
This is because scout processes check neighbours in a clockwise order, and
always select the first suitable neighbour they find. As particles on the
other side of the wall are both boundaries and are within the heading of the
processes, they also qualify as suitable neighbours, so whether a scout
process selects the correct side of the wall depends on the order in which
neighbours are checked.

Essentially, the paratroopers look at their immediate surroundings in a
clockwise order. The right paratrooper always finds the ground and knows where
to step. The left paratrooper finds the Upside Down from Stranger Things and
teleports there.

This bug also affects refraction into and out of thin walls, but since these
walls are thin, the path the PHOT takes inside them is rather short and the
incorrect angle of travel is difficult to see. Furthermore, upon exit, the
same normal deduction bug causes the PHOT to take a path whose angle is almost
identical to that of the path that took it to the wall, so much so that it is
also difficult to see over shorter distances.

The solution is to have the left scout process check neighbours in reverse
order, so that it prefers the right side of the wall over the wrong one. This
does not affect its behaviour when facing thicker walls, but fixes its
behaviour when facing two-layer walls.

The changes in this commit also make find_next_boundary interact with
is_blocking directly to detect a change between the blocking trait of
immediate neighbours. This makes more sense than relying on is_boundary
because find_next_boundary is meant to find a transition from non-blocking to
blocking neighbours within the current heading, rather than to find any
boundary particle. The difference is subtle but important.
2022-11-12 11:10:43 +01:00
..
elements Make stickman movement strength independent of gravity (#857) 2022-09-25 14:49:43 +02:00
simtools Add AMBP and AMBM tools (#778) 2021-07-29 17:50:24 +02:00
Air.cpp Add custom gravity mode and replace hardcoded gravity interactions (#820) 2022-07-31 08:19:16 +02:00
Air.h ensure air doesn't "leak" out of TTAN containers when loading stamps and saves 2017-08-02 23:49:51 -04:00
BuiltinGOL.h Custom GOL (#731) 2020-10-08 20:23:59 +02:00
CoordStack.h Fix clang 8 compile warnings 2019-10-04 00:21:10 -04:00
Element.cpp Custom GOL (#731) 2020-10-08 20:23:59 +02:00
Element.h Mesonification 2020-12-14 20:16:52 +01:00
ElementClasses.cpp Ditch element and tool classes 2020-01-09 19:22:11 +01:00
ElementClasses.h Ditch element and tool classes 2020-01-09 19:22:11 +01:00
ElementCommon.h Mesonification 2020-12-14 20:16:52 +01:00
ElementDefs.h Clean up GameSave somewhat 2022-11-10 15:15:10 +01:00
ElementGraphics.h redo spark graphics, add spark render setting 2014-08-11 21:56:40 -04:00
ElementNumbers.template.h Mesonification 2020-12-14 20:16:52 +01:00
GOLString.cpp Fix render failing to compile with GCC 11 2021-12-07 16:44:48 +01:00
GOLString.h Add a few more Lua functions 2021-08-27 23:57:55 -04:00
Gravity.cpp Fix a metric ton of MSVC warnings 2021-02-15 21:24:44 +01:00
Gravity.h Mesonification 2020-12-14 20:16:52 +01:00
MenuSection.h Move TPT's icons to the (real) Private Use Area of the unicode 2018-05-01 07:03:48 +03:00
meson.build Optimise undo history memory usage 2021-08-04 17:19:15 +02:00
Particle.cpp Alias dcolor, pavg0, pavg1 to dcolour, tmp3, tmp4 2022-08-08 08:55:32 +02:00
Particle.h Alias dcolor, pavg0, pavg1 to dcolour, tmp3, tmp4 2022-08-08 08:55:32 +02:00
Sample.h Flatten include trees 2019-04-20 15:36:11 +02:00
SaveRenderer.cpp Remove GameSave::Collapse and GameSave::originalData 2022-11-10 12:03:48 +01:00
SaveRenderer.h Remove long defunct OpenGL code paths 2022-10-11 20:11:14 +02:00
Sign.cpp Clean up GameSave somewhat 2022-11-10 15:15:10 +01:00
Sign.h Clean up GameSave somewhat 2022-11-10 15:15:10 +01:00
SimTool.cpp Upgrade to C++17 (#819) 2021-12-13 14:41:02 +01:00
SimTool.h Ditch element and tool classes 2020-01-09 19:22:11 +01:00
Simulation.cpp Fix PHOT reflecting off thin walls of particles incorrectly 2022-11-12 11:10:43 +01:00
Simulation.h Fix PHOT reflecting off thin walls of particles incorrectly 2022-11-12 11:10:43 +01:00
SimulationData.cpp Custom GOL (#731) 2020-10-08 20:23:59 +02:00
SimulationData.h Mesonification 2020-12-14 20:16:52 +01:00
Snapshot.h Unbundle bzip2 and jsoncpp, update tpt-libs 2022-10-20 23:15:49 +02:00
SnapshotDelta.cpp Upgrade to C++17 (#819) 2021-12-13 14:41:02 +01:00
SnapshotDelta.h Optimise undo history memory usage 2021-08-04 17:19:15 +02:00
Stickman.h fix STKM + fan wall 2018-03-21 23:58:27 -04:00
StorageClasses.h Flatten include trees 2019-04-20 15:36:11 +02:00
StructProperty.h Alias dcolor, pavg0, pavg1 to dcolour, tmp3, tmp4 2022-08-08 08:55:32 +02:00
ToolClasses.cpp Ditch element and tool classes 2020-01-09 19:22:11 +01:00
ToolClasses.h Ditch element and tool classes 2020-01-09 19:22:11 +01:00
ToolCommon.h Mesonification 2020-12-14 20:16:52 +01:00
ToolNumbers.template.h Mesonification 2020-12-14 20:16:52 +01:00
WallType.h Switch from std::string to String/ByteString in most of the code 2018-04-30 21:13:24 +03:00