From 619d1cd262a49afb9e862ff3b680a1640619427b Mon Sep 17 00:00:00 2001 From: Marek Wydmuch Date: Thu, 26 Feb 2026 23:01:47 +0100 Subject: [PATCH 1/7] Update lemon.c to compile on newer gcc version --- src/vizdoom/tools/lemon/lemon.c | 41 +++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/vizdoom/tools/lemon/lemon.c b/src/vizdoom/tools/lemon/lemon.c index bdc004a17..b5b2cff2e 100644 --- a/src/vizdoom/tools/lemon/lemon.c +++ b/src/vizdoom/tools/lemon/lemon.c @@ -53,7 +53,11 @@ extern int access(char *path, int mode); #endif static int showPrecedenceConflict = 0; -static void *msort(void *list, void *next, int (*cmp)()); +static void *msort( + void *list, + void *next, + int (*cmp)(const char *, const char *) +); /* ** Compilers are getting increasingly pedantic about type conversions @@ -72,12 +76,12 @@ static struct action *Action_new(void); static struct action *Action_sort(struct action *); /********** From the file "build.h" ************************************/ -void FindRulePrecedences(); -void FindFirstSets(); -void FindStates(); -void FindLinks(); -void FindFollowSets(); -void FindActions(); +void FindRulePrecedences(struct lemon *); +void FindFirstSets(struct lemon *); +void FindStates(struct lemon *); +void FindLinks(struct lemon *); +void FindFollowSets(struct lemon *); +void FindActions(struct lemon *); /********* From the file "configlist.h" *********************************/ void Configlist_init(void); @@ -403,10 +407,10 @@ static struct action *Action_new(void){ ** positive if the first action is less than, equal to, or greater than ** the first */ -static int actioncmp(ap1,ap2) -struct action *ap1; -struct action *ap2; +static int actioncmp(const char *_ap1, const char *_ap2) { + const struct action *ap1 = (const struct action *)_ap1; + const struct action *ap2 = (const struct action *)_ap2; int rc; rc = ap1->sp->index - ap2->sp->index; if( rc==0 ){ @@ -1757,7 +1761,12 @@ int main(int argc, char **argv) ** The "next" pointers for elements in the lists a and b are ** changed. */ -static void *merge(void *a,void *b,int (*cmp)(),size_t offset) +static void *merge( + void *a, + void *b, + int (*cmp)(const char *, const char *), + size_t offset +) { char *ptr, *head; @@ -1805,7 +1814,11 @@ static void *merge(void *a,void *b,int (*cmp)(),size_t offset) ** The "next" pointers for elements in list are changed. */ #define LISTSIZE 30 -static void *msort(void *list,void *next,int (*cmp)()) +static void *msort( + void *list, + void *next, + int (*cmp)(const char *, const char *) +) { size_t offset; char *ep; @@ -2714,9 +2727,7 @@ static void preprocess_input(char *z){ } } -int strip_crlf(filebuf, filesize) -char *filebuf; -int filesize; +int strip_crlf(char *filebuf, int filesize) { int i, j; From 2100de63f9821efb0c36e39fa30737ba6d36a6dd Mon Sep 17 00:00:00 2001 From: Marek Wydmuch Date: Thu, 26 Feb 2026 23:32:24 +0100 Subject: [PATCH 2/7] Fix bug reported in #688 Co-Authored-By: MajorDavidZhang --- src/vizdoom/src/viz_game.cpp | 2 +- tests/test_get_state.py | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/vizdoom/src/viz_game.cpp b/src/vizdoom/src/viz_game.cpp index b2c7f52e5..2fbbf8583 100644 --- a/src/vizdoom/src/viz_game.cpp +++ b/src/vizdoom/src/viz_game.cpp @@ -637,7 +637,7 @@ void VIZ_GameStateUpdateSectors(){ VIZSector *vizSector = &vizGameStateSM->SECTOR[sectorCount++]; vizSector->ceilingHeight = VIZ_FixedToDouble(sector->ceilingplane.d); - vizSector->floorHeight = VIZ_FixedToDouble(sector->floorplane.d); + vizSector->floorHeight = -VIZ_FixedToDouble(sector->floorplane.d); unsigned int sectorLineCount = 0; for(int l = 0; l < sector->linecount; ++l){ diff --git a/tests/test_get_state.py b/tests/test_get_state.py index 79d2a4830..2cf9a849a 100755 --- a/tests/test_get_state.py +++ b/tests/test_get_state.py @@ -339,6 +339,28 @@ def test_types(): ) +def test_map01_sectors_floor_not_above_ceiling(): + game = vzd.DoomGame() + try: + game.set_window_visible(False) + game.set_doom_map("map01") + game.set_sectors_info_enabled(True) + game.init() + + state = game.get_state() + assert state is not None, "Expected valid state after init" + assert state.sectors is not None, "Expected sectors info to be available" + assert len(state.sectors) > 0, "Expected at least one sector on map01" + + for i, sector in enumerate(state.sectors): + assert sector.floor_height <= sector.ceiling_height, ( + f"Sector #{i}: floor_height={sector.floor_height} should be <= " + f"ceiling_height={sector.ceiling_height}" + ) + finally: + game.close() + + def test_modifing_buffers_while_game_is_running(): game = vzd.DoomGame() game.set_window_visible(False) From 66c29c68720e515372ad130853d2029e2e7659d8 Mon Sep 17 00:00:00 2001 From: Marek Wydmuch Date: Thu, 26 Feb 2026 23:57:54 +0100 Subject: [PATCH 3/7] Add more z-axis tests --- tests/test_get_state.py | 92 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/tests/test_get_state.py b/tests/test_get_state.py index 2cf9a849a..b2db55d53 100755 --- a/tests/test_get_state.py +++ b/tests/test_get_state.py @@ -14,6 +14,9 @@ import vizdoom as vzd +GEOMETRY_TOLERANCE = 1e-5 + + def _test_get_state( num_iterations=10, num_states=20, @@ -339,6 +342,56 @@ def test_types(): ) +def _point_on_segment_2d(px, py, x1, y1, x2, y2, tolerance=GEOMETRY_TOLERANCE): + dx = x2 - x1 + dy = y2 - y1 + cross = (px - x1) * dy - (py - y1) * dx + if abs(cross) > tolerance * max(1.0, abs(dx), abs(dy)): + return False + + # Dot product is <= 0 when (px, py) is between segment endpoints. + dot = (px - x1) * (px - x2) + (py - y1) * (py - y2) + return dot <= tolerance + + +def _point_in_sector_2d(px, py, sector, tolerance=GEOMETRY_TOLERANCE): + inside = False + for line in sector.lines: + x1, y1 = line.x1, line.y1 + x2, y2 = line.x2, line.y2 + + if _point_on_segment_2d(px, py, x1, y1, x2, y2, tolerance): + return True + + intersects = (y1 > py) != (y2 > py) + if intersects: + x_intersection = (x2 - x1) * (py - y1) / (y2 - y1) + x1 + if px < x_intersection: + inside = not inside + + return inside + + +def _find_object_sector(obj, sectors, tolerance=GEOMETRY_TOLERANCE): + containing = [ + sector + for sector in sectors + if _point_in_sector_2d(obj.position_x, obj.position_y, sector, tolerance) + ] + if not containing: + return None + + candidate_with_floor_below = [ + sector + for sector in containing + if obj.position_z + tolerance >= sector.floor_height + ] + if candidate_with_floor_below: + return max(candidate_with_floor_below, key=lambda sector: sector.floor_height) + + return min(containing, key=lambda sector: abs(obj.position_z - sector.floor_height)) + + def test_map01_sectors_floor_not_above_ceiling(): game = vzd.DoomGame() try: @@ -348,7 +401,6 @@ def test_map01_sectors_floor_not_above_ceiling(): game.init() state = game.get_state() - assert state is not None, "Expected valid state after init" assert state.sectors is not None, "Expected sectors info to be available" assert len(state.sectors) > 0, "Expected at least one sector on map01" @@ -361,6 +413,44 @@ def test_map01_sectors_floor_not_above_ceiling(): game.close() +def test_map01_objects_are_above_the_floor_of_their_sector(): + game = vzd.DoomGame() + try: + game.set_window_visible(False) + game.set_doom_map("map01") + game.set_objects_info_enabled(True) + game.set_sectors_info_enabled(True) + game.init() + + state = game.get_state() + assert state.objects is not None, "Expected objects info to be available" + assert state.sectors is not None, "Expected sectors info to be available" + assert len(state.objects) > 0, "Expected at least one object on map01" + assert len(state.sectors) > 0, "Expected at least one sector on map01" + + errors = [] + for obj in state.objects: + sector = _find_object_sector(obj, state.sectors) + if sector is None: + errors.append( + f"Object id={obj.id}, name={obj.name} was not matched to any sector " + f"at (x={obj.position_x}, y={obj.position_y}, z={obj.position_z})" + ) + continue + + if obj.position_z + GEOMETRY_TOLERANCE < sector.floor_height: + errors.append( + f"Object id={obj.id}, name={obj.name} is below floor: " + f"z={obj.position_z}, sector_floor={sector.floor_height}" + ) + + assert not errors, "Object-to-sector floor validation failed:\n" + "\n".join( + errors + ) + finally: + game.close() + + def test_modifing_buffers_while_game_is_running(): game = vzd.DoomGame() game.set_window_visible(False) From 5d09e7b90b9446832d0996c49ada884a690eec52 Mon Sep 17 00:00:00 2001 From: Marek Wydmuch Date: Fri, 27 Feb 2026 00:03:58 +0100 Subject: [PATCH 4/7] Update docs --- docs/api/cpp/game_state.md | 2 +- docs/api/python/game_state.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/cpp/game_state.md b/docs/api/cpp/game_state.md index df0b5a84c..718f74965 100644 --- a/docs/api/cpp/game_state.md +++ b/docs/api/cpp/game_state.md @@ -141,7 +141,7 @@ Note: added in 1.1.8. ### `Sector` (`C++ type / Python type` **name**) -- `double / float` **floorHeight / floor_height** +- `double / float` **floorHeight / floor_height** - Note: before 1.3.1 the value of floorHeight was inverted (negative). The bug was fixed in 1.3.1. - `double / float` **ceilingHeight / ceiling_height** - `std::vector