Hello,
as you might know, i reworked the gameplay code and hopefully you will soon
see the results of that. As i proceeded, playturn.cpp became smaller and
smaller (i moved the functionality elsewhere) and finally only the
networking part of the code was left. Then i thought: "It would be really
nice to once and for all remove all that network dependencies that really
should not be there". So i examined what was left, especially the references
(includes) to playturn.hpp. There weren't many left but the ones that are
provide a more difficult problem. As an example, i take the code in
actions.cpp, that is using a turn_info object. Like this code that resides
in ai.cpp::recruit :
...
if(recruit_unit(info_.map,info_.team_num,info_.units,new_unit,loc,preference
s::show_ai_moves() ? &info_.disp : NULL).empty()) {
...
info_.turn_data_.sync_network();
...
return true;
else if(...
Almost impossible to get it out of there using "conventional" mechanisms.
You would have to isolate the statements before and after the sync_network
call into separate blocks of code (for example methods) and then try to
extract the call out of there. Very difficult because there is an enclosing
if-statement that you have to deal with.
There is another option: you can delay the call until the rest of the code
within recruit is done, that makes extracting very easy. But that has a
tradeoff: Immediate feedback is lost. If things turn out bad you might have
to wait until the end of the turn until you send the results to other
network players.
I don't feel comfortable with both of these possibilities. So i started to
think about alternatives. The only satisfying one i can think of at the
moment is implementing an event handling mechanism. An event actually is
nothing else than a list of callback functions that get called when the
event fires. As i write these lines i think of events.cpp. And voila, this
is pretty much what i am thinking about. The only difference is that it is
focused on SDL events which i don't have in mind here. What i think of is
more like a generic event handling mechanism. But the functionality is very
much alike.
So what would change within action.cpp::recruit if we use events?
1.
Instead of calling sync_network directly an event gets fired. sync_network
is attached as a event handler to that event and therefore gets called just
like it did before, BUT: action.cpp only knows of function pointers, it does
not need to know the functions itself. So it does not need a reference to
playturn.hpp, it only needs to know that it calls a void function without
arguments. And heureka: The dependency vanishes into dust!
2.
What might be even more important: The rest of the code does not need to be
changed at all. The only thing you need to do is define an event within
action.cpp (like "fire_sync" or something) and substitute the function call.
The rest is done outside of actions.cpp, that is attaching the event handler
to that event. It is done where it belongs to: In a part of the code that
needs to deal with networking.
This mechanism is not restricted to this specific example. Its generic
nature makes it applicable almost everywhere. I think especially of the
class "display", that has a whole lot of things in it that i don't think
belong there.
So, what do you think? Should we give it a try and use this technique? If
there are no objections i would go and set up a generic event class, then
try to rework the above example. I would just do it right away (well, after
i merged my current work, maybe ;-) but this is something we should agree
about because it could change the way the code is working fundamentally. Any
suggestions/comments/whatever are highly welcome :-)
Greetings to everyone
Yogi
_______________________________________________
Wesnoth-dev mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-dev