Flowfield prototype

For code related discussions and questions
Perl99
New user
Posts: 5
Joined: 10 Nov 2018, 20:01

Flowfield prototype

Post by Perl99 »

Hello,

I have implemented prototype of flowfield pathfinding algorithm and I need some help. The concept is here:
http://www.gameaipro.com/GameAIPro/Game ... _Tiles.pdf
Example: https://youtu.be/Bspb9g9nTto?t=113

It's about generating vector field, directing to goal(s). It's strength is that we can have the same field for any number of units, moving to the same goal. It also enables further development of steering behavior and collision & obstacle avoidance, because there is no need for path recalculation each time an unit is forced to avoid something. It's more expensive to generate than A*, though.

This is my first contribution to WZ and I know maybe 1% of codebase. I have rough prototype ready, but I have trouble integrating it into existing code.

The algorithm generates both A* path and the flowfield. The path is used as approximation until flowfield is ready. Right now I only integrated the path, and droids should ignore the path as soon as flowfield is available. But WZ code seems tightly coupled to path and I don't know how to deal with it. The current direction vector from flowfield should be merged with current movement direction to make turning smooth.

The prototype has some limitations:
  • It does not analyze owner side of the droids (that might be problematic)
  • It does not care about danger/threat map (that might be easy)
  • It assumes FMT_BLOCK (that should be easy to change, tiles blocked by structure would go into integration field)
  • It does not update anything when structures are created / destroyed. (I have to write code to invalidate stuff and rebuild some, it might be tricky with already moving droids)
  • Included debug draw code is very hacky, as I don't know how to draw stuff on tiles correctly (current code works acceptably only on initial zoom and rotation)
  • I used some stuff from Qt, because I didn't know about plans to get rid of it. It's QElapsedTimer (for debug only), QThreadPool and QCache. I decided that first I would like to have it working and then to have it working good.
  • I haven't tested it with savegames, and probably loading a save will make all moving droids to stop.
  • No idea how it will behave in MP games, no code for debugSync has been made.
  • I have compiled it with MSVC 2017 on Windows, and this compiler is known not to conform to standards (although it gets better).
  • Currently there is only one goal - x,y where player has clicked. But the code can support an area of goals (for example, for preserving formation). It might have edge cases, but it is already used internally.
  • There is no Line-of-sight pass, as described in the article. I considered it too complicated, and not-that-much beneficial. It's about ignoring the flowfield and moving directly to goal. What is WZ already doing for VTOLs.
I hope someone can help me with integration or give some directions and explanations of code related to movement.

The code: https://github.com/Perl99/warzone2100/t ... -prototype
Run with

Code: Select all

--flowfield
User avatar
vexed
Inactive
Inactive
Posts: 2538
Joined: 27 Jul 2010, 02:07

Re: Flowfield prototype

Post by vexed »

I was looking into doing something like this years( :oops: ) ago, and just never had the time to finish anything.

We were given the source "as is", without any documentation at all, just what you see in the source, and even then, there have been times when those docs aren't actually doing what it says it is doing.

I am not sure who last touched the code, or even knows all the in's & out's of it, so, unsure who would be the best person to point you to. Perhaps Cyp or maybe Per can answer some more detailed questions, but, I think they both did the bare minimum with that side of the source.

I am not around much these days either, busy with RL stuff, so, basically, I wish you luck, WZ is really in need of these kind of enhancements to make the game more enjoyable for all!

Haven't had a chance to look at what you are doing before I leave again, but, IIRC, there are some GPL compatible flowfield (and steering) type libraries out there, unsure if you are using that or not, but I always favor stuff that has been out for awhile to get the kinks out over something home-brewed, and it needs to be deterministic, or it will cause desync errors.
/facepalm ...Grinch stole Warzone🙈🙉🙊 contra principia negantem non est disputandum
Super busy, don't expect a timely reply back.
Perl99
New user
Posts: 5
Joined: 10 Nov 2018, 20:01

Re: Flowfield prototype

Post by Perl99 »

All is coded by me, except for Qt stuff. I wanted to have more control over it. I have only found some simple examples on the web so far, no libraries.
I'm not sure if the code is 100% deterministic. It is divided into tasks, computed in parallel, which might get slightly different order. That could result in different times when a part of the flowfield is available to different players. So droids might take slightly different paths (maybe). That part is still missing, so that is my guess.

I just hoped there is someone who touched the code in move.cpp, maybe fixed a few bugs and has and idea what is going there.
User avatar
NoQ
Special
Special
Posts: 6226
Joined: 24 Dec 2009, 11:35
Location: /var/zone

Re: Flowfield prototype

Post by NoQ »

No idea how it will behave in MP games, no code for debugSync has been made.
The overall idea is to make the behavior entirely deterministic. Your code should not rely on wall-clock timeouts but should instead rely on timeouts formulated in terms of game frames, should not use floating-point arithmetic but should instead use integer arithmetic, should not use standard library's random values but should use the game's custom Mersenne Twister that yields the same result on all machines across the network, etc.

As far as i understand, the current pathfinder is implemented as follows:
  1. Clients agree on the lag value L (say, "L = 2 game-frames", which amounts to 200ms) that is computed deterministically based on mutual ping values. Not sure if this value changes throughout the game.
  2. Every order given by the player to its units is delayed by the lag value. I.e., if the order is given on frame N, units will only start moving on frame (N + L). But the pathfinder is already allowed to run in the background thread as soon as the order was given locally.
  3. Similarly, if the order for the opponent's unit is received from the network, it is timestamped with the value (N + L) on which it starts executing, but pathfinding starts immediately. Such pathfinding is guaranteed to yield the same result on all machines due to determinism.
  4. The lag value ensures that the game can run smoothly because whenever it has received full information about frame N, it can precisely predict the future until frame (N + L) inclusively.
  5. If the game has displayed everything it can predict to the user but it requires more inputs to proceed, it hangs and displays the "Zzz" icon. Such inputs may include packets from other peers on the network or results of pathfinding that are received from the background thread on indeterministic moments of wall time. In particular, if a certain peer cannot finish pathfinding in time, it will keep all other peers hanging until its own pathfinding thread yields results, because only then will it be able to send information about the next game frame.
Cyp
Evitcani
Evitcani
Posts: 784
Joined: 17 Jan 2010, 23:35

Re: Flowfield prototype

Post by Cyp »

I think that's almost right, except that I think pathfinding has to start at the same game time, since the result depends on the game state at the time it starts.
Per
Warzone 2100 Team Member
Warzone 2100 Team Member
Posts: 3780
Joined: 03 Aug 2006, 19:39

Re: Flowfield prototype

Post by Per »

Note that the generation of the path/flow only needs to be deterministic if the same computation needs to be done on each peer. If the droid owner does the path/flow computation and then sends it to the other peers over the network, and they can follow this path/flow deterministically from a common point in the future, then that will also work. This would also likely reduce the CPU load a lot, since not everyone then needs to do all the path/flow calculations, but only their own.
Forgon
Code contributor
Code contributor
Posts: 298
Joined: 07 Dec 2016, 22:23

Re: Flowfield prototype

Post by Forgon »

Perl99 wrote: 10 Nov 2018, 21:40 [...] The code: https://github.com/Perl99/warzone2100/t ... -prototype
Run with

Code: Select all

--flowfield
Unfortunately, I failed to compile your prototype.

After executing `./autogen.sh && ./configure CFLAGS='-O2 -gstabs -g -g3 -pipe' CXXFLAGS='-O2 -gstabs -g -g3 -pipe' && make -j6`, I encountered a warning about an MSVC-specific pragma:

Code: Select all

In file included from clparse.cpp:45:
flowfield.h:4: error: ignoring #pragma warning  [-Werror=unknown-pragmas]
 #pragma warning(disable: 4201)
After silencing it by adding '-Wno-unknown-pragmas' to CFLAGS and CXXFLAGS, I ran into linker errors:

Code: Select all

/usr/bin/ld: clparse.o: in function `ParseCommandLine(int, char const* const*)':
/home/x/flowfield/warzone2100/src/clparse.cpp:663: undefined reference to `flowfield::enable()'
/usr/bin/ld: display3d.o: in function `draw3DScene()':
/home/x/flowfield/warzone2100/src/display3d.cpp:902: undefined reference to `flowfield::debugDraw()'
/usr/bin/ld: fpath.o: in function `fpathDroidRoute(DROID*, int, int, FPATH_MOVETYPE)':
/home/x/flowfield/warzone2100/src/fpath.cpp:453: undefined reference to `flowfield::isEnabled()'
/usr/bin/ld: /home/x/flowfield/warzone2100/src/fpath.cpp:454: undefined reference to `flowfield::getPathFromCache(unsigned int, unsigned int, unsigned int, unsigned int, PROPULSION_TYPE)'
/usr/bin/ld: /home/x/flowfield/warzone2100/src/fpath.cpp:461: undefined reference to `flowfield::portalPathToCoordsPath(std::deque<unsigned int, std::allocator<unsigned int> > const&, DROID*)'
/usr/bin/ld: /home/x/flowfield/warzone2100/src/fpath.cpp:466: undefined reference to `flowfield::calculateFlowFieldsAsync(MOVE_CONTROL*, unsigned int, int, int, int, int, PROPULSION_TYPE, DROID_TYPE, FPATH_MOVETYPE, int, bool, StructureBounds const&)'
/usr/bin/ld: init.o: in function `systemShutdown()':
/home/x/flowfield/warzone2100/src/init.cpp:766: undefined reference to `flowfield::destroy()'
/usr/bin/ld: init.o: in function `stageThreeInitialise()':
/home/x/flowfield/warzone2100/src/init.cpp:1211: undefined reference to `flowfield::init()'
/usr/bin/ld: init.o: in function `stageThreeShutDown()':
/home/x/flowfield/warzone2100/src/init.cpp:1329: undefined reference to `flowfield::destroy()'
collect2: error: ld returned 1 exit status
Edit: Due to some forum software bug, I cannot upload the log file with the linker errors. Visit http://ix.io/1vW6 to view it.
Its name was supposed to be: "flowfield_prototype_autotools_linker_errors.log"
Its description was supposed to be: "output of `make -j6` after executing `./autogen.sh && ./configure CFLAGS='-O2 -gstabs -g -g3 -pipe -Wno-unknown-pragmas' CXXFLAGS='-O2 -gstabs -g -g3 -pipe -Wno-unknown-pragmas'`"

The error message I receive reads as follows:

Code: Select all

General Error
You are not allowed to access this file.

BACKTRACE

FILE: (not given by php)
LINE: (not given by php)
CALL: msg_handler()

FILE: [ROOT]/includes/message_parser.php
LINE: 1873
CALL: trigger_error()

FILE: [ROOT]/posting.php
LINE: 614
CALL: parse_message->get_submitted_attachment_data()
Attachments
flowfield_prototype_autotools_unknown_pragma.log
output of `make -j6` after executing `./autogen.sh && ./configure CFLAGS='-O2 -gstabs -g -g3 -pipe' CXXFLAGS='-O2 -gstabs -g -g3 -pipe'`
(163.97 KiB) Downloaded 337 times
User avatar
Berserk Cyborg
Code contributor
Code contributor
Posts: 938
Joined: 26 Sep 2016, 19:56

Re: Flowfield prototype

Post by Berserk Cyborg »

Forgon wrote: After silencing it by adding '-Wno-unknown-pragmas' to CFLAGS and CXXFLAGS, I ran into linker errors:
I think the flowfield.* files are missing in src/Makefile.am. I ran into some errors with the qt elapsed timers so I didn't get a successful compile yet.
Perl99
New user
Posts: 5
Joined: 10 Nov 2018, 20:01

Re: Flowfield prototype

Post by Perl99 »

Clearly missing from Makefile. I'm sure I have added it because I had linkage errors too. Could be that I haven't committed this file.

That pragma is because MSVC gave me error about nameless struct in GLM, so I had to disable it.
QT elapsed timer is only used for debug, you can safely comment out /remove it.

If you don't want to have debug view, undefine / comment out a flag named "I_AM_FLOW_FIELD_MAINTAINER_AND_WANT_TO_HAVE_MY_VIEW_OBSCURED" in flowfield.h. I haven't yet found a way to move this flag to Makefile with possibility to enable / disable it at build preparation.
pastdue
Warzone 2100 Team Member
Warzone 2100 Team Member
Posts: 339
Joined: 13 Aug 2017, 17:44

Re: Flowfield prototype

Post by pastdue »

Going forward, since the CMake build setup should now work on all platforms, I think the focus will be there (and the autotools / Makefile build setup, which is less flexible and more brittle, may end up going away).
Forgon
Code contributor
Code contributor
Posts: 298
Joined: 07 Dec 2016, 22:23

Re: Flowfield prototype

Post by Forgon »

The prototype was updated a few days ago.
Unfortunately, I still fail to compile with autotools. Shortened output of `make -j 6`:

Code: Select all

[...]
In file included from flowfield.cpp:6:
flowfield.private.h:218:35: error: extra qualification ‘flowfield::detail::AbstractAStar::’ on member ‘reconstructPath’ [-fpermissive]
    const std::deque<unsigned int> AbstractAStar::reconstructPath(unsigned int start);
                                   ^~~~~~~~~~~~~
flowfield.private.h: In member function ‘void flowfield::detail::FuturedTask<T>::run()’:
flowfield.private.h:266:6: error: ‘QElapsedTimer’ was not declared in this scope
      QElapsedTimer timer;
      ^~~~~~~~~~~~~
flowfield.private.h:266:6: note: suggested alternative: ‘QDateTime’
      QElapsedTimer timer;
      ^~~~~~~~~~~~~
      QDateTime
flowfield.private.h:267:6: error: ‘timer’ was not declared in this scope
      timer.start();
      ^~~~~
flowfield.private.h:267:6: note: suggested alternative: ‘time’
      timer.start();
      ^~~~~
      time
flowfield.private.h:273:40: error: ‘logMutex’ was not declared in this scope
       std::lock_guard<std::mutex> lock(logMutex);
                                        ^~~~~~~~
flowfield.private.h:280:40: error: ‘logMutex’ was not declared in this scope
       std::lock_guard<std::mutex> lock(logMutex);
                                        ^~~~~~~~
flowfield.private.h: In member function ‘void flowfield::detail::FlowFieldSector::VectorT::normalize()’:
flowfield.private.h:331:32: error: ‘sqrt’ is not a member of ‘std’
      const float length = std::sqrt(std::pow(x, 2) + std::pow(y, 2));
                                ^~~~
flowfield.private.h:331:32: note: suggested alternative: ‘sort’
      const float length = std::sqrt(std::pow(x, 2) + std::pow(y, 2));
                                ^~~~
                                sort
flowfield.private.h:331:42: error: ‘pow’ is not a member of ‘std’
      const float length = std::sqrt(std::pow(x, 2) + std::pow(y, 2));
                                          ^~~
flowfield.private.h:331:59: error: ‘pow’ is not a member of ‘std’
      const float length = std::sqrt(std::pow(x, 2) + std::pow(y, 2));
                                                           ^~~
flowfield.private.h: At global scope:
flowfield.private.h:388:4: error: type qualifiers ignored on function return type [-Werror=ignored-qualifiers]
    const unsigned short getCostOrElse(const short x, const short y, const unsigned short elseCost);
    ^~~~~
flowfield.private.h:420:3: error: type qualifiers ignored on function return type [-Werror=ignored-qualifiers]
   const unsigned int straightLineDistance(const Point source, const Point destination);
   ^~~~~
[...]
flowfield.cpp: In function ‘void flowfield::calculateFlowFieldsAsync(MOVE_CONTROL*, unsigned int, int, int, int, int, PROPULSION_TYPE, DROID_TYPE, FPATH_MOVETYPE, int, bool, const StructureBounds&)’:
flowfield.cpp:72:117: error: no matching function for call to ‘flowfield::detail::Point::Point(<brace-enclosed initializer list>)’
   detail::Point source { static_cast<unsigned int>(map_coord(startX)), static_cast<unsigned int>(map_coord(startY)) };
                                                                                                                     ^
In file included from flowfield.cpp:6:
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point()’
   struct Point {
          ^~~~~
flowfield.private.h:73:10: note:   candidate expects 0 arguments, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(const flowfield::detail::Point&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(flowfield::detail::Point&&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.cpp:73:107: error: no matching function for call to ‘flowfield::detail::Point::Point(<brace-enclosed initializer list>)’
   detail::Point goal { static_cast<unsigned int>(map_coord(tX)), static_cast<unsigned int>(map_coord(tY)) };
                                                                                                           ^
In file included from flowfield.cpp:6:
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point()’
   struct Point {
          ^~~~~
flowfield.private.h:73:10: note:   candidate expects 0 arguments, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(const flowfield::detail::Point&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(flowfield::detail::Point&&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.cpp:75:20: error: ‘make_unique’ is not a member of ‘std’
   auto task = std::make_unique<detail::PathRequestTask>(source, goal, propulsionType);
                    ^~~~~~~~~~~
flowfield.cpp:75:20: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:25:1:
+#include <memory>
 
flowfield.cpp:75:20:
   auto task = std::make_unique<detail::PathRequestTask>(source, goal, propulsionType);
                    ^~~~~~~~~~~
flowfield.cpp:75:55: error: expected primary-expression before ‘>’ token
   auto task = std::make_unique<detail::PathRequestTask>(source, goal, propulsionType);
                                                       ^
flowfield.cpp:75:65: error: left operand of comma operator has no effect [-Werror=unused-value]
   auto task = std::make_unique<detail::PathRequestTask>(source, goal, propulsionType);
                                                                 ^~~~
flowfield.cpp:75:71: error: right operand of comma operator has no effect [-Werror=unused-value]
   auto task = std::make_unique<detail::PathRequestTask>(source, goal, propulsionType);
                                                                       ^~~~~~~~~~~~~~
flowfield.cpp: In function ‘std::deque<unsigned int> flowfield::getPathFromCache(unsigned int, unsigned int, unsigned int, unsigned int, PROPULSION_TYPE)’:
flowfield.cpp:81:117: error: no matching function for call to ‘flowfield::detail::Point::Point(<brace-enclosed initializer list>)’
   detail::Point source { static_cast<unsigned int>(map_coord(startX)), static_cast<unsigned int>(map_coord(startY)) };
                                                                                                                     ^
In file included from flowfield.cpp:6:
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point()’
   struct Point {
          ^~~~~
flowfield.private.h:73:10: note:   candidate expects 0 arguments, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(const flowfield::detail::Point&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(flowfield::detail::Point&&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.cpp:82:107: error: no matching function for call to ‘flowfield::detail::Point::Point(<brace-enclosed initializer list>)’
   detail::Point goal { static_cast<unsigned int>(map_coord(tX)), static_cast<unsigned int>(map_coord(tY)) };
                                                                                                           ^
In file included from flowfield.cpp:6:
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point()’
   struct Point {
          ^~~~~
flowfield.private.h:73:10: note:   candidate expects 0 arguments, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(const flowfield::detail::Point&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(flowfield::detail::Point&&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.cpp: In function ‘const std::pair<float, float> flowfield::getMovementVector(unsigned int, unsigned int, unsigned int, PROPULSION_TYPE)’:
flowfield.cpp:92:84: error: could not convert ‘{currentX, currentY}’ from ‘<brace-enclosed initializer list>’ to ‘flowfield::detail::Point’
   return detail::getMovementVector(nextPortalId, { currentX, currentY }, propulsion);
                                                                                    ^
flowfield.cpp: At global scope:
flowfield.cpp:169:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:169:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:169:37: error: expected primary-expression before ‘>’ token
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
                                     ^
flowfield.cpp:170:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:170:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:170:37: error: expected primary-expression before ‘>’ token
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
                                     ^
flowfield.cpp:171:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:171:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:171:37: error: expected primary-expression before ‘>’ token
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
                                     ^
flowfield.cpp:172:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX)
         ^~~~~~~~~~~
flowfield.cpp:172:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:172:37: error: expected primary-expression before ‘>’ token
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX)
                                     ^
flowfield.cpp:176:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:176:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:176:36: error: expected primary-expression before ‘>’ token
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
                                    ^
flowfield.cpp:177:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:177:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:177:36: error: expected primary-expression before ‘>’ token
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
                                    ^
flowfield.cpp:178:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:178:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:178:36: error: expected primary-expression before ‘>’ token
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
                                    ^
flowfield.cpp:179:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX)
         ^~~~~~~~~~~
flowfield.cpp:179:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:179:36: error: expected primary-expression before ‘>’ token
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX)
                                    ^
flowfield.cpp: In static member function ‘static flowfield::detail::Point flowfield::detail::AbstractSector::getTopLeftCorner(unsigned int)’:
flowfield.cpp:249:21: error: no matching function for call to ‘flowfield::detail::Point::Point(<brace-enclosed initializer list>)’
    return Point{x, y};
                     ^
In file included from flowfield.cpp:6:
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point()’
   struct Point {
          ^~~~~
flowfield.private.h:73:10: note:   candidate expects 0 arguments, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(const flowfield::detail::Point&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(flowfield::detail::Point&&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.cpp: In member function ‘const std::deque<unsigned int> flowfield::detail::PathRequestTask::portalWalker(unsigned int, unsigned int)’:
flowfield.cpp:582:121: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
     std::deque<unsigned int> path = portalWalker.findPath(sourcePortalId, static_cast<const unsigned int>(portals.size()));
                                                                                                                         ^
flowfield.cpp:585:26: error: ‘make_unique’ is not a member of ‘std’
     auto pathCopy = std::make_unique<std::deque<unsigned int>>(path);
                          ^~~~~~~~~~~
flowfield.cpp:585:26: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:585:61: error: expected primary-expression before ‘>’ token
     auto pathCopy = std::make_unique<std::deque<unsigned int>>(path);
                                                             ^~
flowfield.cpp: In member function ‘std::vector<std::future<bool> > flowfield::detail::PathRequestTask::scheduleFlowFields(std::deque<unsigned int>&)’:
flowfield.cpp:610:23: error: ‘make_unique’ is not a member of ‘std’
      auto task = std::make_unique<FlowfieldCalcTask>(goals, portals, sectors, propulsion);
                       ^~~~~~~~~~~
flowfield.cpp:610:23: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:610:52: error: expected primary-expression before ‘>’ token
      auto task = std::make_unique<FlowfieldCalcTask>(goals, portals, sectors, propulsion);
                                                    ^
flowfield.cpp:610:61: error: left operand of comma operator has no effect [-Werror=unused-value]
      auto task = std::make_unique<FlowfieldCalcTask>(goals, portals, sectors, propulsion);
                                                             ^~~~~~~
flowfield.cpp:610:61: error: right operand of comma operator has no effect [-Werror=unused-value]
flowfield.cpp:610:70: error: right operand of comma operator has no effect [-Werror=unused-value]
      auto task = std::make_unique<FlowfieldCalcTask>(goals, portals, sectors, propulsion);
                                                                      ^~~~~~~
flowfield.cpp:625:22: error: ‘make_unique’ is not a member of ‘std’
     auto task = std::make_unique<FlowfieldCalcTask>(finalGoals, portals, sectors, propulsion);
                      ^~~~~~~~~~~
flowfield.cpp:625:22: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:625:51: error: expected primary-expression before ‘>’ token
     auto task = std::make_unique<FlowfieldCalcTask>(finalGoals, portals, sectors, propulsion);
                                                   ^
flowfield.cpp:625:65: error: left operand of comma operator has no effect [-Werror=unused-value]
     auto task = std::make_unique<FlowfieldCalcTask>(finalGoals, portals, sectors, propulsion);
                                                                 ^~~~~~~
flowfield.cpp:625:65: error: right operand of comma operator has no effect [-Werror=unused-value]
flowfield.cpp:625:74: error: right operand of comma operator has no effect [-Werror=unused-value]
     auto task = std::make_unique<FlowfieldCalcTask>(finalGoals, portals, sectors, propulsion);
                                                                          ^~~~~~~
flowfield.cpp: In member function ‘virtual void flowfield::detail::FlowfieldCalcTask::runPromised()’:
flowfield.cpp:668:32: error: ‘make_unique’ is not a member of ‘std’
     auto flowfieldMoved = std::make_unique<FlowFieldSector>(std::move(flowField));
                                ^~~~~~~~~~~
flowfield.cpp:668:32: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:668:59: error: expected primary-expression before ‘>’ token
     auto flowfieldMoved = std::make_unique<FlowFieldSector>(std::move(flowField));
                                                           ^
flowfield.cpp: In member function ‘void flowfield::detail::FlowfieldCalcTask::calculateIntegrationField(const pointsT&)’:
flowfield.cpp:680:57: error: no matching function for call to ‘flowfield::detail::Tile::Tile(<brace-enclosed initializer list>)’
      integrationField.setTile(x, y, Tile { NOT_PASSABLE });
                                                         ^
In file included from flowfield.cpp:6:
flowfield.private.h:66:10: note: candidate: ‘constexpr flowfield::detail::Tile::Tile()’
   struct Tile {
          ^~~~
flowfield.private.h:66:10: note:   candidate expects 0 arguments, 1 provided
flowfield.private.h:66:10: note: candidate: ‘constexpr flowfield::detail::Tile::Tile(const flowfield::detail::Tile&)’
flowfield.private.h:66:10: note:   no known conversion for argument 1 from ‘const short unsigned int’ to ‘const flowfield::detail::Tile&’
flowfield.private.h:66:10: note: candidate: ‘constexpr flowfield::detail::Tile::Tile(flowfield::detail::Tile&&)’
flowfield.private.h:66:10: note:   no known conversion for argument 1 from ‘const short unsigned int’ to ‘flowfield::detail::Tile&&’
flowfield.cpp: In member function ‘void flowfield::detail::FlowfieldCalcTask::integratePoints(std::priority_queue<flowfield::detail::FlowfieldCalcTask::Node>&)’:
flowfield.cpp:718:71: error: no matching function for call to ‘flowfield::detail::Tile::Tile(<brace-enclosed initializer list>)’
     integrationField.setTile(nodePoint.x, nodePoint.y, Tile { newCost });
                                                                       ^
In file included from flowfield.cpp:6:
flowfield.private.h:66:10: note: candidate: ‘constexpr flowfield::detail::Tile::Tile()’
   struct Tile {
          ^~~~
flowfield.private.h:66:10: note:   candidate expects 0 arguments, 1 provided
flowfield.private.h:66:10: note: candidate: ‘constexpr flowfield::detail::Tile::Tile(const flowfield::detail::Tile&)’
flowfield.private.h:66:10: note:   no known conversion for argument 1 from ‘const short unsigned int’ to ‘const flowfield::detail::Tile&’
flowfield.private.h:66:10: note: candidate: ‘constexpr flowfield::detail::Tile::Tile(flowfield::detail::Tile&&)’
flowfield.private.h:66:10: note:   no known conversion for argument 1 from ‘const short unsigned int’ to ‘flowfield::detail::Tile&&’
flowfield.cpp: In member function ‘void flowfield::detail::FlowfieldCalcTask::calculateFlowField()’:
flowfield.cpp:727:23: error: unused variable ‘thisSectorId’ [-Werror=unused-variable]
    const unsigned int thisSectorId = AbstractSector::getIdByCoords(goals[0].x, goals[0].y);
                       ^~~~~~~~~~~~
flowfield.cpp: At global scope:
flowfield.cpp:764:3: error: type qualifiers ignored on function return type [-Werror=ignored-qualifiers]
   const unsigned short FlowfieldCalcTask::getCostOrElse(const short x, const short y, const unsigned short elseCost) {
   ^~~~~
flowfield.cpp: In function ‘void flowfield::detail::initCostFields()’:
flowfield.cpp:792:29: error: ‘make_unique’ is not a member of ‘std’
      sectors.push_back(std::make_unique<Sector>());
                             ^~~~~~~~~~~
flowfield.cpp:792:29: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:792:47: error: expected primary-expression before ‘>’ token
      sectors.push_back(std::make_unique<Sector>());
                                               ^
flowfield.cpp:792:49: error: expected primary-expression before ‘)’ token
      sectors.push_back(std::make_unique<Sector>());
                                                 ^
flowfield.cpp: In function ‘void flowfield::detail::costFieldReplaceWithEmpty(flowfield::detail::sectorListT&)’:
flowfield.cpp:825:20: error: ‘make_unique’ is not a member of ‘std’
      sector = std::make_unique<EmptySector>();
                    ^~~~~~~~~~~
flowfield.cpp:825:20: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:825:43: error: expected primary-expression before ‘>’ token
      sector = std::make_unique<EmptySector>();
                                           ^
flowfield.cpp:825:45: error: expected primary-expression before ‘)’ token
      sector = std::make_unique<EmptySector>();
                                             ^
flowfield.cpp: In function ‘flowfield::detail::Tile flowfield::detail::createTile(unsigned int, unsigned int, PROPULSION_TYPE)’:
flowfield.cpp:955:20: error: no matching function for call to ‘flowfield::detail::Tile::Tile(<brace-enclosed initializer list>)’
    return Tile{cost};
                    ^
In file included from flowfield.cpp:6:
flowfield.private.h:66:10: note: candidate: ‘constexpr flowfield::detail::Tile::Tile()’
   struct Tile {
          ^~~~
flowfield.private.h:66:10: note:   candidate expects 0 arguments, 1 provided
flowfield.private.h:66:10: note: candidate: ‘constexpr flowfield::detail::Tile::Tile(const flowfield::detail::Tile&)’
flowfield.private.h:66:10: note:   no known conversion for argument 1 from ‘short unsigned int’ to ‘const flowfield::detail::Tile&’
flowfield.private.h:66:10: note: candidate: ‘constexpr flowfield::detail::Tile::Tile(flowfield::detail::Tile&&)’
flowfield.private.h:66:10: note:   no known conversion for argument 1 from ‘short unsigned int’ to ‘flowfield::detail::Tile&&’
flowfield.cpp: In function ‘flowfield::detail::Portal flowfield::detail::detectPortalByAxis(unsigned int, unsigned int, unsigned int, unsigned int, bool, flowfield::detail::AbstractSector&, flowfield::detail::AbstractSector&, unsigned int&)’:
flowfield.cpp:971:50: error: no matching function for call to ‘flowfield::detail::Point::Point(<brace-enclosed initializer list>)’
      firstSectorPoint = Point { axis, otherAxis1 };
                                                  ^
In file included from flowfield.cpp:6:
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point()’
   struct Point {
          ^~~~~
flowfield.private.h:73:10: note:   candidate expects 0 arguments, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(const flowfield::detail::Point&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(flowfield::detail::Point&&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.cpp:972:51: error: no matching function for call to ‘flowfield::detail::Point::Point(<brace-enclosed initializer list>)’
      secondSectorPoint = Point { axis, otherAxis2 };
                                                   ^
In file included from flowfield.cpp:6:
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point()’
   struct Point {
          ^~~~~
flowfield.private.h:73:10: note:   candidate expects 0 arguments, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(const flowfield::detail::Point&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(flowfield::detail::Point&&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.cpp:976:50: error: no matching function for call to ‘flowfield::detail::Point::Point(<brace-enclosed initializer list>)’
      firstSectorPoint = Point { otherAxis1, axis };
                                                  ^
In file included from flowfield.cpp:6:
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point()’
   struct Point {
          ^~~~~
flowfield.private.h:73:10: note:   candidate expects 0 arguments, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(const flowfield::detail::Point&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(flowfield::detail::Point&&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.cpp:977:51: error: no matching function for call to ‘flowfield::detail::Point::Point(<brace-enclosed initializer list>)’
      secondSectorPoint = Point { otherAxis2, axis };
                                                   ^
In file included from flowfield.cpp:6:
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point()’
   struct Point {
          ^~~~~
flowfield.private.h:73:10: note:   candidate expects 0 arguments, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(const flowfield::detail::Point&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(flowfield::detail::Point&&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.cpp: In function ‘flowfield::detail::Point flowfield::detail::getPointByFlatIndex(unsigned int)’:
flowfield.cpp:1036:24: error: no matching function for call to ‘flowfield::detail::Point::Point(<brace-enclosed initializer list>)’
    return Point { x, y };
                        ^
In file included from flowfield.cpp:6:
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point()’
   struct Point {
          ^~~~~
flowfield.private.h:73:10: note:   candidate expects 0 arguments, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(const flowfield::detail::Point&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.private.h:73:10: note: candidate: ‘constexpr flowfield::detail::Point::Point(flowfield::detail::Point&&)’
flowfield.private.h:73:10: note:   candidate expects 1 argument, 2 provided
flowfield.cpp: At global scope:
flowfield.cpp:1070:3: error: type qualifiers ignored on function return type [-Werror=ignored-qualifiers]
   const unsigned int straightLineDistance(const Point source, const Point destination) {
   ^~~~~
[...]
In file included from ../lib/framework/string_ext.h:24,
                 from ../lib/framework/frame.h:44,
                 from ../lib/framework/vector.h:31,
                 from basedef.h:29,
                 from droiddef.h:31,
                 from fpath.h:27,
                 from flowfield.h:8,
                 from flowfield.cpp:5:
flowfield.private.h: In instantiation of ‘void flowfield::detail::FuturedTask<T>::run() [with T = bool]’:
flowfield.private.h:264:9:   required from here
flowfield.private.h:281:24: error: too many arguments for format [-Werror=format-extra-args]
       debug(LOG_ERROR, "Exception in thread pool worker: ", ex.what());
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../lib/framework/debug.h:264:93: note: in definition of macro ‘debug’
 #define debug(part, ...) do { if (enabled_debug[part]) _debug(__LINE__, part, __FUNCTION__, __VA_ARGS__); } while(0)
                                                                                             ^~~~~~~~~~~
cc1plus: all warnings being treated as errors
make[3]: *** [Makefile:1059: flowfield.o] Error 1
make[3]: *** Waiting for unfinished jobs....
make[3]: Leaving directory '/home/x/flowfield/warzone2100/src'
make[2]: *** [Makefile:853: all] Error 2
make[2]: Leaving directory '/home/x/flowfield/warzone2100/src'
make[1]: *** [Makefile:583: all-recursive] Error 1
make[1]: Leaving directory '/home/x/flowfield/warzone2100'
make: *** [Makefile:503: all] Error 2
I also failed to compile with cmake using the instructions from our Linux Compile Guide, but for reasons unrelated to the prototype.

Output of `cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH=~/flowfield -GNinja`:

Code: Select all

CMake Warning at CMakeLists.txt:10 (message):
  Portable build is only supported on Windows; Ignoring WZ_PORTABLE option


-- Supports COMPILER_FLAG [C]: -Wpedantic ... YES
-- Supports COMPILER_FLAG [CXX]: -Wpedantic ... YES
-- Supports COMPILER_FLAG [C]: -Wall ... YES
-- Supports COMPILER_FLAG [CXX]: -Wall ... YES
-- Supports COMPILER_FLAG [C]: -Wextra ... YES
-- Supports COMPILER_FLAG [CXX]: -Wextra ... YES
-- Supports COMPILER_FLAG [C]: -Wcast-align ... YES
-- Supports COMPILER_FLAG [CXX]: -Wcast-align ... YES
-- Supports COMPILER_FLAG [C]: -Wcast-qual ... YES
-- Supports COMPILER_FLAG [CXX]: -Wcast-qual ... YES
-- Supports COMPILER_FLAG [C]: -Winit-self ... YES
-- Supports COMPILER_FLAG [CXX]: -Winit-self ... YES
-- Supports COMPILER_FLAG [CXX]: -Wnoexcept ... YES
-- Supports COMPILER_FLAG [CXX]: -Woverloaded-virtual ... YES
-- Supports COMPILER_FLAG [CXX]: -Wstrict-null-sentinel ... YES
-- Supports COMPILER_FLAG [C]: -Wwrite-strings ... YES
-- Supports COMPILER_FLAG [CXX]: -Wwrite-strings ... YES
-- Supports COMPILER_FLAG [C]: -Wpointer-arith ... YES
-- Supports COMPILER_FLAG [CXX]: -Wpointer-arith ... YES
-- Supports COMPILER_FLAG [C]: -Wstrict-prototypes ... YES
-- Supports COMPILER_FLAG [C]: -Wmissing-noreturn ... YES
-- Supports COMPILER_FLAG [CXX]: -Wmissing-noreturn ... YES
-- Supports COMPILER_FLAG [CXX]: -Wnon-virtual-dtor ... YES
-- Supports COMPILER_FLAG [C]: -Wnull-dereference ... YES
-- Supports COMPILER_FLAG [CXX]: -Wnull-dereference ... YES
-- Supports COMPILER_FLAG [C]: -Wduplicated-cond ... YES
-- Supports COMPILER_FLAG [CXX]: -Wduplicated-cond ... YES
-- Supports COMPILER_FLAG [C]: -Walloc-zero ... YES
-- Supports COMPILER_FLAG [CXX]: -Walloc-zero ... YES
-- Supports COMPILER_FLAG [C]: -Walloca-larger-than=1024 ... YES
-- Supports COMPILER_FLAG [CXX]: -Walloca-larger-than=1024 ... YES
-- Supports COMPILER_FLAG [C]: -Wrestrict ... YES
-- Supports COMPILER_FLAG [CXX]: -Wrestrict ... YES
-- Supports COMPILER_FLAG [C]: -Werror ... YES
-- Supports COMPILER_FLAG [CXX]: -Werror ... YES
-- Supports COMPILER_FLAG [C]: -Wno-error=logical-op ... YES
-- Supports COMPILER_FLAG [CXX]: -Wno-error=logical-op ... YES
-- Supports COMPILER_FLAG [C]: -Wno-error=sign-compare ... YES
-- Supports COMPILER_FLAG [CXX]: -Wno-error=sign-compare ... YES
-- Supports COMPILER_FLAG [C]: -Wno-error=format-security ... YES
-- Supports COMPILER_FLAG [CXX]: -Wno-error=format-security ... YES
-- Supports COMPILER_FLAG [C]: -Wno-unused-parameter ... YES
-- Supports COMPILER_FLAG [CXX]: -Wno-unused-parameter ... YES
-- Supports COMPILER_FLAG [C]: -Wno-stringop-truncation ... YES
-- Supports COMPILER_FLAG [CXX]: -Wno-stringop-truncation ... YES
-- Supports COMPILER_FLAG [C]: -Wno-format-truncation ... YES
-- Supports COMPILER_FLAG [CXX]: -Wno-format-truncation ... YES
-- Supported C compiler_flags= -Wpedantic -Wall -Wextra -Wcast-align -Wcast-qual -Winit-self -Wwrite-strings -Wpointer-arith -Wstrict-prototypes -Wmissing-noreturn -Wnull-dereference -Wduplicated-cond -Walloc-zero -Walloca-larger-than=1024 -Wrestrict -Werror -Wno-error=logical-op -Wno-error=sign-compare -Wno-error=format-security -Wno-unused-parameter -Wno-stringop-truncation -Wno-format-truncation
-- Supported CXX compiler_flags= -Wpedantic -Wall -Wextra -Wcast-align -Wcast-qual -Winit-self -Wnoexcept -Woverloaded-virtual -Wstrict-null-sentinel -Wwrite-strings -Wpointer-arith -Wmissing-noreturn -Wnon-virtual-dtor -Wnull-dereference -Wduplicated-cond -Walloc-zero -Walloca-larger-than=1024 -Wrestrict -Werror -Wno-error=logical-op -Wno-error=sign-compare -Wno-error=format-security -Wno-unused-parameter -Wno-stringop-truncation -Wno-format-truncation
CMake Warning (dev) at /usr/share/cmake-3.13/Modules/FindOpenGL.cmake:270 (message):
  Policy CMP0072 is not set: FindOpenGL prefers GLVND by default when
  available.  Run "cmake --help-policy CMP0072" for policy details.  Use the
  cmake_policy command to set the policy and suppress this warning.

  FindOpenGL found both a legacy GL library:

    OPENGL_gl_LIBRARY: /usr/lib/libGL.so

  and GLVND libraries for OpenGL and GLX:

    OPENGL_opengl_LIBRARY: /usr/lib/libOpenGL.so
    OPENGL_glx_LIBRARY: /usr/lib/libGLX.so

  OpenGL_GL_PREFERENCE has not been set to "GLVND" or "LEGACY", so for
  compatibility with CMake 3.10 and below the legacy GL library will be used.
Call Stack (most recent call first):
  lib/ivis_opengl/CMakeLists.txt:45 (find_package)
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Set TARGET warzone2100 LINK_FLAG: -Wl,-z,relro ... YES (cached)
-- Set TARGET warzone2100 LINK_FLAG: -Wl,-z,now ... YES (cached)
-- 7z supports switch: -bb0 ... YES
-- Could NOT find Asciidoctor (missing: Asciidoctor_COMMAND) 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/x/flowfield/warzone2100/build
Output of `cmake --build build --target install`:

Code: Select all

[1/254] Building CXX object lib/framework/CMakeFiles/framework.dir/utf.cpp.o
[2/254] Building CXX object lib/framework/CMakeFiles/framework.dir/resource_lexer.cpp.o
FAILED: lib/framework/CMakeFiles/framework.dir/resource_lexer.cpp.o 
/usr/bin/c++  -DHAVE_CONFIG_H -DQT_CORE_LIB -DQT_NO_DEBUG -DUTF8PROC_STATIC -DYY_NO_UNISTD_H -D_CRT_SECURE_NO_WARNINGS -I. -I../. -I../3rdparty -I../3rdparty/glm -I../3rdparty/miniupnp -I../3rdparty/micro-ecc/.. -I../3rdparty/sha2/.. -isystem /usr/include/qt -isystem /usr/include/qt/QtCore -isystem /usr/lib/qt/mkspecs/linux-g++ -Wno-error -fstack-protector-strong  -Wpedantic -Wall -Wextra -Wcast-align -Wcast-qual -Winit-self -Wnoexcept -Woverloaded-virtual -Wstrict-null-sentinel -Wwrite-strings -Wpointer-arith -Wmissing-noreturn -Wnon-virtual-dtor -Wnull-dereference -Wduplicated-cond -Walloc-zero -Walloca-larger-than=1024 -Wrestrict -Werror -Wno-error=logical-op -Wno-error=sign-compare -Wno-error=format-security -Wno-unused-parameter -Wno-stringop-truncation -Wno-format-truncation -O2 -g -DNDEBUG -fPIC   -fPIC -std=gnu++11 -MD -MT lib/framework/CMakeFiles/framework.dir/resource_lexer.cpp.o -MF lib/framework/CMakeFiles/framework.dir/resource_lexer.cpp.o.d -o lib/framework/CMakeFiles/framework.dir/resource_lexer.cpp.o -c ../lib/framework/resource_lexer.cpp
resource_lexer.cpp: In function ‘int res_lex()’:
resource_lexer.cpp:1207:12: error: potential null pointer dereference [-Werror=null-dereference]
resource_lexer.cpp:1205:30: error: potential null pointer dereference [-Werror=null-dereference]
cc1plus: all warnings being treated as errors
[3/254] Building CXX object lib/framework/CMakeFiles/framework.dir/strres_lexer.cpp.o
FAILED: lib/framework/CMakeFiles/framework.dir/strres_lexer.cpp.o 
/usr/bin/c++  -DHAVE_CONFIG_H -DQT_CORE_LIB -DQT_NO_DEBUG -DUTF8PROC_STATIC -DYY_NO_UNISTD_H -D_CRT_SECURE_NO_WARNINGS -I. -I../. -I../3rdparty -I../3rdparty/glm -I../3rdparty/miniupnp -I../3rdparty/micro-ecc/.. -I../3rdparty/sha2/.. -isystem /usr/include/qt -isystem /usr/include/qt/QtCore -isystem /usr/lib/qt/mkspecs/linux-g++ -Wno-error -fstack-protector-strong  -Wpedantic -Wall -Wextra -Wcast-align -Wcast-qual -Winit-self -Wnoexcept -Woverloaded-virtual -Wstrict-null-sentinel -Wwrite-strings -Wpointer-arith -Wmissing-noreturn -Wnon-virtual-dtor -Wnull-dereference -Wduplicated-cond -Walloc-zero -Walloca-larger-than=1024 -Wrestrict -Werror -Wno-error=logical-op -Wno-error=sign-compare -Wno-error=format-security -Wno-unused-parameter -Wno-stringop-truncation -Wno-format-truncation -O2 -g -DNDEBUG -fPIC   -fPIC -std=gnu++11 -MD -MT lib/framework/CMakeFiles/framework.dir/strres_lexer.cpp.o -MF lib/framework/CMakeFiles/framework.dir/strres_lexer.cpp.o.d -o lib/framework/CMakeFiles/framework.dir/strres_lexer.cpp.o -c ../lib/framework/strres_lexer.cpp
strres_lexer.cpp: In function ‘int strres_lex()’:
strres_lexer.cpp:1178:12: error: potential null pointer dereference [-Werror=null-dereference]
strres_lexer.cpp:1176:30: error: potential null pointer dereference [-Werror=null-dereference]
cc1plus: all warnings being treated as errors
[4/254] Building CXX object lib/framework/CMakeFiles/framework.dir/trig.cpp.o
[5/254] Building CXX object lib/gamelib/CMakeFiles/gamelib.dir/audp_lexer.cpp.o
[6/254] Building CXX object lib/framework/CMakeFiles/framework.dir/wzstring.cpp.o
../lib/framework/wzstring.cpp: In member function ‘WzString& WzString::leftPadToMinimumLength(const WzUniCodepoint&, size_t)’:
../lib/framework/wzstring.cpp:500:15: warning: comparison of integer expressions of different signedness: ‘int’ and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
  if (length() >= minimumStringLength)
      ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
[7/254] Building CXX object lib/framework/CMakeFiles/framework.dir/wzconfig.cpp.o
ninja: build stopped: subcommand failed.
Attachments
flowfield_prototype_cmake_install.log
output of `cmake --build build --target install`
(3.76 KiB) Downloaded 313 times
flowfield_prototype_cmake_build.log
output of `cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH=~/flowfield -GNinja`
(4.72 KiB) Downloaded 337 times
flowfield_prototype_cmake_install.log
output of `cmake --build build --target install`
(3.76 KiB) Downloaded 320 times
flowfield_prototype_cmake_build.log
output of `cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH=/home/x/flowfield -GNinja`
(4.72 KiB) Downloaded 294 times
flowfield_prototype_autotools.log
output of `make -j6` after executing `./autogen.sh && ./configure CFLAGS='-O2 -gstabs -g -g3 -pipe' CXXFLAGS='-O2 -gstabs -g -g3 -pipe'`
(28.96 KiB) Downloaded 327 times
Perl99
New user
Posts: 5
Joined: 10 Nov 2018, 20:01

Re: Flowfield prototype

Post by Perl99 »

I have fixed the errors.
It's mostly about MSVC not being fully compliant to the standard. Two things with struct brace init are C++14 thing, I guess GCC uses C++11.

Could you try compiling it again?
Forgon
Code contributor
Code contributor
Posts: 298
Joined: 07 Dec 2016, 22:23

Re: Flowfield prototype

Post by Forgon »

Perl99 wrote: 22 Dec 2018, 13:55 I have fixed the errors.
It's mostly about MSVC not being fully compliant to the standard. Two things with struct brace init are C++14 thing, I guess GCC uses C++11.

Could you try compiling it again?
I tried your latest version, but still fail to compile with autotools. Shortened output of `make -j 6`:

Code: Select all

[...]
In file included from flowfield.cpp:6:
flowfield.private.h: In member function ‘void flowfield::detail::FuturedTask<T>::run()’:
flowfield.private.h:276:40: error: ‘logMutex’ was not declared in this scope
       std::lock_guard<std::mutex> lock(logMutex);
                                        ^~~~~~~~
flowfield.private.h:276:40: note: suggested alternative: ‘log2f64x’
       std::lock_guard<std::mutex> lock(logMutex);
                                        ^~~~~~~~
                                        log2f64x
flowfield.private.h:283:40: error: ‘logMutex’ was not declared in this scope
       std::lock_guard<std::mutex> lock(logMutex);
                                        ^~~~~~~~
flowfield.private.h:283:40: note: suggested alternative: ‘log2f64x’
       std::lock_guard<std::mutex> lock(logMutex);
                                        ^~~~~~~~
                                        log2f64x
[...]
flowfield.cpp: In function ‘void flowfield::calculateFlowFieldsAsync(MOVE_CONTROL*, unsigned int, int, int, int, int, PROPULSION_TYPE, DROID_TYPE, FPATH_MOVETYPE, int, bool, const StructureBounds&)’:
flowfield.cpp:75:20: error: ‘make_unique’ is not a member of ‘std’
   auto task = std::make_unique<detail::PathRequestTask>(source, goal, propulsionType);
                    ^~~~~~~~~~~
flowfield.cpp:75:20: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:25:1:
+#include <memory>
 
flowfield.cpp:75:20:
   auto task = std::make_unique<detail::PathRequestTask>(source, goal, propulsionType);
                    ^~~~~~~~~~~
flowfield.cpp:75:55: error: expected primary-expression before ‘>’ token
   auto task = std::make_unique<detail::PathRequestTask>(source, goal, propulsionType);
                                                       ^
flowfield.cpp:75:65: error: left operand of comma operator has no effect [-Werror=unused-value]
   auto task = std::make_unique<detail::PathRequestTask>(source, goal, propulsionType);
                                                                 ^~~~
flowfield.cpp:75:71: error: right operand of comma operator has no effect [-Werror=unused-value]
   auto task = std::make_unique<detail::PathRequestTask>(source, goal, propulsionType);
                                                                       ^~~~~~~~~~~~~~
flowfield.cpp: At global scope:
flowfield.cpp:169:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:169:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:169:37: error: expected primary-expression before ‘>’ token
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
                                     ^
flowfield.cpp:170:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:170:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:170:37: error: expected primary-expression before ‘>’ token
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
                                     ^
flowfield.cpp:171:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:171:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:171:37: error: expected primary-expression before ‘>’ token
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX),
                                     ^
flowfield.cpp:172:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX)
         ^~~~~~~~~~~
flowfield.cpp:172:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:172:37: error: expected primary-expression before ‘>’ token
    std::make_unique<portalPathCacheT>(PORTAL_PATH_CACHE_MAX)
                                     ^
flowfield.cpp:176:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:176:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:176:36: error: expected primary-expression before ‘>’ token
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
                                    ^
flowfield.cpp:177:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:177:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:177:36: error: expected primary-expression before ‘>’ token
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
                                    ^
flowfield.cpp:178:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
         ^~~~~~~~~~~
flowfield.cpp:178:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:178:36: error: expected primary-expression before ‘>’ token
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX),
                                    ^
flowfield.cpp:179:9: error: ‘make_unique’ is not a member of ‘std’
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX)
         ^~~~~~~~~~~
flowfield.cpp:179:9: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:179:36: error: expected primary-expression before ‘>’ token
    std::make_unique<flowfieldCacheT>(FLOWFIELD_CACHE_MAX)
                                    ^
flowfield.cpp: In member function ‘const std::deque<unsigned int> flowfield::detail::PathRequestTask::portalWalker(unsigned int, unsigned int)’:
flowfield.cpp:582:121: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
     std::deque<unsigned int> path = portalWalker.findPath(sourcePortalId, static_cast<const unsigned int>(portals.size()));
                                                                                                                         ^
flowfield.cpp:585:26: error: ‘make_unique’ is not a member of ‘std’
     auto pathCopy = std::make_unique<std::deque<unsigned int>>(path);
                          ^~~~~~~~~~~
flowfield.cpp:585:26: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:585:61: error: expected primary-expression before ‘>’ token
     auto pathCopy = std::make_unique<std::deque<unsigned int>>(path);
                                                             ^~
flowfield.cpp: In member function ‘std::vector<std::future<bool> > flowfield::detail::PathRequestTask::scheduleFlowFields(std::deque<unsigned int>&)’:
flowfield.cpp:610:23: error: ‘make_unique’ is not a member of ‘std’
      auto task = std::make_unique<FlowfieldCalcTask>(goals, portals, sectors, propulsion);
                       ^~~~~~~~~~~
flowfield.cpp:610:23: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:610:52: error: expected primary-expression before ‘>’ token
      auto task = std::make_unique<FlowfieldCalcTask>(goals, portals, sectors, propulsion);
                                                    ^
flowfield.cpp:610:61: error: left operand of comma operator has no effect [-Werror=unused-value]
      auto task = std::make_unique<FlowfieldCalcTask>(goals, portals, sectors, propulsion);
                                                             ^~~~~~~
flowfield.cpp:610:61: error: right operand of comma operator has no effect [-Werror=unused-value]
flowfield.cpp:610:70: error: right operand of comma operator has no effect [-Werror=unused-value]
      auto task = std::make_unique<FlowfieldCalcTask>(goals, portals, sectors, propulsion);
                                                                      ^~~~~~~
flowfield.cpp:625:22: error: ‘make_unique’ is not a member of ‘std’
     auto task = std::make_unique<FlowfieldCalcTask>(finalGoals, portals, sectors, propulsion);
                      ^~~~~~~~~~~
flowfield.cpp:625:22: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:625:51: error: expected primary-expression before ‘>’ token
     auto task = std::make_unique<FlowfieldCalcTask>(finalGoals, portals, sectors, propulsion);
                                                   ^
flowfield.cpp:625:65: error: left operand of comma operator has no effect [-Werror=unused-value]
     auto task = std::make_unique<FlowfieldCalcTask>(finalGoals, portals, sectors, propulsion);
                                                                 ^~~~~~~
flowfield.cpp:625:65: error: right operand of comma operator has no effect [-Werror=unused-value]
flowfield.cpp:625:74: error: right operand of comma operator has no effect [-Werror=unused-value]
     auto task = std::make_unique<FlowfieldCalcTask>(finalGoals, portals, sectors, propulsion);
                                                                          ^~~~~~~
flowfield.cpp: In member function ‘virtual void flowfield::detail::FlowfieldCalcTask::runPromised()’:
flowfield.cpp:668:32: error: ‘make_unique’ is not a member of ‘std’
     auto flowfieldMoved = std::make_unique<FlowFieldSector>(std::move(flowField));
                                ^~~~~~~~~~~
flowfield.cpp:668:32: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:668:59: error: expected primary-expression before ‘>’ token
     auto flowfieldMoved = std::make_unique<FlowFieldSector>(std::move(flowField));
                                                           ^
flowfield.cpp: In function ‘void flowfield::detail::initCostFields()’:
flowfield.cpp:790:29: error: ‘make_unique’ is not a member of ‘std’
      sectors.push_back(std::make_unique<Sector>());
                             ^~~~~~~~~~~
flowfield.cpp:790:29: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:790:47: error: expected primary-expression before ‘>’ token
      sectors.push_back(std::make_unique<Sector>());
                                               ^
flowfield.cpp:790:49: error: expected primary-expression before ‘)’ token
      sectors.push_back(std::make_unique<Sector>());
                                                 ^
flowfield.cpp: In function ‘void flowfield::detail::costFieldReplaceWithEmpty(flowfield::detail::sectorListT&)’:
flowfield.cpp:823:20: error: ‘make_unique’ is not a member of ‘std’
      sector = std::make_unique<EmptySector>();
                    ^~~~~~~~~~~
flowfield.cpp:823:20: note: ‘std::make_unique’ is defined in header ‘<memory>’; did you forget to ‘#include <memory>’?
flowfield.cpp:823:43: error: expected primary-expression before ‘>’ token
      sector = std::make_unique<EmptySector>();
                                           ^
flowfield.cpp:823:45: error: expected primary-expression before ‘)’ token
      sector = std::make_unique<EmptySector>();
                                             ^
[...]
In file included from ../lib/framework/string_ext.h:24,
                 from ../lib/framework/frame.h:44,
                 from ../lib/framework/vector.h:31,
                 from basedef.h:29,
                 from droiddef.h:31,
                 from fpath.h:27,
                 from flowfield.h:8,
                 from flowfield.cpp:5:
flowfield.private.h: In instantiation of ‘void flowfield::detail::FuturedTask<T>::run() [with T = bool]’:
flowfield.private.h:267:9:   required from here
flowfield.private.h:278:28: error: format ‘%d’ expects argument of type ‘int’, but argument 6 has type ‘long long int’ [-Werror=format=]
       debug(LOG_FLOWFIELD, "FuturedTask (%s) took %d ms", typeid(*this).name(), took);
                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~                        ~~~~
../lib/framework/debug.h:264:93: note: in definition of macro ‘debug’
 #define debug(part, ...) do { if (enabled_debug[part]) _debug(__LINE__, part, __FUNCTION__, __VA_ARGS__); } while(0)
                                                                                             ^~~~~~~~~~~
cc1plus: all warnings being treated as errors
make[3]: *** [Makefile:1059: flowfield.o] Error 1
make[3]: *** Waiting for unfinished jobs....
make[3]: Leaving directory '/home/x/flowfield/warzone2100/src'
make[2]: *** [Makefile:853: all] Error 2
make[2]: Leaving directory '/home/x/flowfield/warzone2100/src'
make[1]: *** [Makefile:583: all-recursive] Error 1
make[1]: Leaving directory '/home/x/flowfield/warzone2100'
make: *** [Makefile:503: all] Error 2
Attachments
flowfield_prototype_autotools.log
output of `make -j6` after executing `./autogen.sh && ./configure CFLAGS='-O2 -gstabs -g -g3 -pipe' CXXFLAGS='-O2 -gstabs -g -g3 -pipe'`
(206.07 KiB) Downloaded 295 times
User avatar
Iluvalar
Regular
Regular
Posts: 1828
Joined: 02 Oct 2010, 18:44

Re: Flowfield prototype

Post by Iluvalar »

Per wrote: 23 Nov 2018, 03:02 If the droid owner does the path/flow computation and then sends it to the other peers over the network, and they can follow this path/flow deterministically from a common point in the future, then that will also work. This would also likely reduce the CPU load a lot, since not everyone then needs to do all the path/flow calculations, but only their own.
I would say can't do. The tanks will keep blocking each other and require recalculation. Also on a complicated map, a single tank could require 150 tiles of patfinding. That would be a lot to transfer in the netcode. Running an advanced A* with terrain difficulty wasn't a problem 5 years ago when i tried on 2.3.9 . The good maps are usually fairly open. It's not like a maze. So path finding is nearly linear.
Heretic 2.3 improver and proud of it.
Perl99
New user
Posts: 5
Joined: 10 Nov 2018, 20:01

Re: Flowfield prototype

Post by Perl99 »

So I have fixed more incompatibilities. Compiled with with cmake + gcc 7.3 and got no more errors.
I needed to use C++14 for make_unique<>, is that ok?

The tanks will keep blocking each other and require recalculation. Also on a complicated map, a single tank could require 150 tiles of patfinding.
This flowfield implementation uses 2 levels of pathfinding:
* waypoint-A*, which only visits "sectors" (rectangle of 16x16 tiles currently). It's a list of sectors to visit
* per-sector flowfield, for given path
So if any two droids go from A to B, they will reuse A* path, and then reuse per-sector flowfields.
If a droid wants to go from C to B and C is near A, then probably A* path will be already calculated, and reused. Also some of the flowfields on the path will probably be reused, even if a bit different A* path was calculated.
Post Reply