Difference between revisions of "GSoC-WesnothWhiteboard Gabba"
(→The Project) |
(→Design Notes) |
||
Line 88: | Line 88: | ||
The processing of those planned_actions will happen in the same way that those originating from the current client: they get merged in the vector of planned_actions corresponding to the sender, checked for validity and displayed accordingly. | The processing of those planned_actions will happen in the same way that those originating from the current client: they get merged in the vector of planned_actions corresponding to the sender, checked for validity and displayed accordingly. | ||
− | ==Design Notes== | + | ==Raw and barbaric Design Notes== |
− | '''The following are my design notes up to now, which will | + | '''The following are my design notes up to now, which will disappear as time goes and I organize them into sections. In the meanwhile, what you have below is basically a list of milestones I would implement in order, to get to the desired functionality.''' |
Development steps: | Development steps: |
Revision as of 08:33, 29 March 2010
This page is related to Summer of Code 2010 |
See the list of Summer of Code 2010 Ideas |
This is a Summer of Code 2010 student page |
Description
Gabba - Wesnoth Whiteboard
My original goal for this project was to reduce waiting tedium in coop multiplayer games, by allowing you to see your ally's moves exactly as if you were staring at the same screen while he plays his turn.
This has evolved in a wider Whiteboard project, which will allow you and your allies to visually plan moves on the map together. It will replace the current undo system, which has some kludgy problems and conflicts.
Updated 03/28/2010
IRC
gabm
About Me
See http://wiki.wesnoth.org/User:Gabba.
History
To put things in context, this idea was already discussed in embryonic form
- here: http://www.wesnoth.org/forum/viewtopic.php?f=15&t=26324
- and then here: http://www.wesnoth.org/forum/viewtopic.php?f=12&t=29102&start=0
- and again here: https://mail.gna.org/public/wesnoth-dev/2010-03/msg00001.html
- and finally here: http://wiki.wesnoth.org/GSoC-ShareUndoableMovesWithAllies_Gabba
before it ended up as this formal GSoC proposal.
The Problem
Waiting tedium and difficult allied planning
Currently when playing a coop game (either RPG or more standard multiplayer campaign), there are several things that really irk me when it's not my turn:
- You wait a long time before seeing anything happening (unless your opponents are playing without delay shroud updates).
- When your ally who's taking his turn finally attacks an enemy or makes another non-undoable move, you have to sit through a delayed replay of his moves. If he already finished his turn, your ally has to wait while you watch this.
- After a few undoable moves by either allied player, communication is completely out of sync. If you tell your ally, "look, I'm encircling his leader", he has no clue what you're talking about: he doesn't see what you're doing. If your ally asks you "should I move my white mage here to heal you units next turn", you 1) have no clue about which hex "here" is supposed to mean 2) even if you did, you can't adequately counsel him, since you don't see how he positioned his other units.
For this last point, you can of course place labels all over the place, but this project intends to provide a much more natural way to communicate.
Conflicts between undo and various events
Undo and delay shroud updates are very useful, but several game features conflict with them. You could have 10 temporary moves planned, just to see what your ZOC would look like, but the first of any of these events will makes you lose any undo possibility:
- Triggering an ambush
- Triggering an WML event ("sighted" in particular poses problems)
- Attacking a unit
- etc.
One of the goal of this project is to remove conflicts between planning moves, and this kind of event.
The Project
Overview
Some kind of summary description is needed here, but in the meanwhile you'll have to dive into the raw design notes below.
Interface
Engine
Current state of the game engine
The game state is currently synced between clients through the use of replays. As actions (recruits, moves, attacks, etc.) are executed on the current client (i.e., the client of the player who's playing his turn now), the local replay gets augmented with corresponding commands. Those commands are are stored as WML config objects, and have an undo attribute that indicates if they can still be undone, and a sent attribute that indicates if they have been synced over the network.
Periodically, the current client calls turn_info::send_data(). Through a chain of calls, this function locates non-undoable, non-sent commands (with replay::get_data_range()), and transmits them over the network (network::send_data()) after having placed them in a config object under a [turn] tag.
On the receiving end (i.e. all other clients), replay info is detected in turn_info::process_network_data(), and is eventually processed in do_replay_handle(), which actually replays the actions on the remote clients.
Changes
For this project, I want to completely get rid of the concept of an "undoable action".
Instead, a vector of a new kind of object called planned_action will be maintained on each client. Vectors will all get exchanged between allied clients, so that each ally will end up with a vector of planned_actions per ally in play. (Or alternatively, a vector that contains the planned_actions from all allies, sorted by turn order.) A planned_action will either be a WML config, or have methods to serialize/deserialize easily to it, to allow sending over the network.
- Here I'm using the term vector, but I'll try to stay data-structure-agnostic as much as possible by hiding it under my own interface, so I can for example easily change it to a linked list or a dequeue if it seems desirable.
Current client to allies
This describes the mechanism will allow transmitting planned_actions between players, and in particular will allow the acting player to show his allies what he's planning.
On the current client, the player will have an appropriate interface to plan actions, and will be able to commit them as real actions, either one by one in the order of his choice, or all at once, in the order in which they exist in the planned_action vector. A commit means that the planned_action is deleted, and the corresponding real action performed, and then added to the replay as in the current system.
After each commit, whether it's a single one or part of a sequence, it's very possible that other planned moves will not be realizable. Anything could have happened, from the position of a move now being blocked because the last unit that tried to move got ambushed, to a WML event that could change anything it wants. Therefore, each commit is followed by a validity evaluation of all remaining planned_moves (in this vector and others). Detected conflicts will stop the execution of a commit sequence, and they will be displayed to the player in the interface.
The mechanism of calling send_data() periodically will not change, except that the current client will send together (in the same network::send_data()) any updates to the replay, and any updates to the planned_action vector. Here an important distinction will be made between allies and enemies:
- enemies get sent only updates to the replay
- allies get sent both updates to the replay and planned_moves
On the receiving end of these updates, clients will use turn_info::process_network_data() to process the incoming info as usual. Updates to the gamestate i.e. replay commands will be applied first, followed by updates (if any) to the vector of planned_actions that corresponds to the sender. Then clients will check all planned_moves in all vectors for conflicts with the updated game state.
The simplest approach for updating remotely the vector of planned_moves would be to re-send it completely whenever there's any change to it. However this wastes network bandwith and processing time, and since planned_moves are designed to be displayed on-screen, it might affect their display speed. The preferred approach will therefore be to implement a simple merge algorithm (similar to what is used in version control systems like subversion). Only changes will be transmitted, such as additions and deletions at specific positions in the vector, as well as planned_actions switching places, and all operations that will become necessary.
Other clients to current client
The players who are not having their turn also want to plan actions, and show their currently playing ally (if any) what they intend to do!
Even if it's not their turn, players will still have access to the interface to plan actions. In addition of being available at the beginning of the next turn, the planned_action vector hence created will periodically get transmitted (as we do with chat messages, etc) to all allies, including the ally who's currently having his turn.
The processing of those planned_actions will happen in the same way that those originating from the current client: they get merged in the vector of planned_actions corresponding to the sender, checked for validity and displayed accordingly.
Raw and barbaric Design Notes
The following are my design notes up to now, which will disappear as time goes and I organize them into sections. In the meanwhile, what you have below is basically a list of milestones I would implement in order, to get to the desired functionality.
Development steps:
- Backend work: store an ordered set of actions and detect which ones conflict with the current terrain, units, and so on (for that use isvalid() function defined in AI code). Allow committing them in any order; a commit means the action is executed, deleted from the list, and all other actions are evaluated for validity again. API must allow for deleting an action, (and switching its place in the queue, inserting directly in some place in the queue, etc, but those can be added later.)
- Planned actions are represented by a vector of Planned_Action objects, which are either WML configs, or provide methods to serialize/deserialize easily to those, so they can later be synced on the network and applied on clients in the same manner they're applied locally.
- Allow for commiting all actions in sequence, stopping as soon as an invalid action is detected.
- Sync those actions to the other allied clients. For now since they're supposed to be allies and have the same view of things, Clients receive the conflict status, and don't verify it themselves. (Later, checking will be needed to "suggest" moves.) For now a move commited can just be applied like now (apply replay command), and all planned moves uploaded again to each client.
- More advanced syncing of planned moves: when a move is commited, notify clients so that they execute the right action, identified by its place in the order sequence. Manage the syncing of other types of changes, such as actions switching places and so on.
- Interface to define moves:
- Option A: footsteps or red lines coming from units at their current position, and reuse current attack markers to show where they want to attack. Problem: may get messy and illegible if many lines lead to the same place or cross. Need for something (an alternate display mode with spacebar?) to show future location of units and their ZOC properly, or we can display unit shadows at destination location.
- Option B: units actually move to their planned location; also reuse current attack markers to show planned attacks. Better for clarity. Problem: doesn't allow to plan the movement of several units to the same place, such as 10 walking corpses wanting to attack the same Paladin from the same spot.
- Design choice for option B: how to represent the movement of units to their projected location? We could use replay, and fast-replay every move whenever a change that conflicts with those moves is made. However it's probably better to just move the unit image around, leaving it's real position untouched.
- Design choice for options A and B: if we're not really moving the units to their future location, how to calculate ZOC and possible enemy moves? It's probably possible to use directly or adapt the functions doing those calculations, but it's something to keep in mind.
OPTIONAL/FUTURE DEVELOPMENTS
- Defining moves when it's not our turn. This simply allows player B to add actions for his own units to the queue while player A is doing his turn. If player A is an ally, player B will see both the moves he defined and the moves his ally defined. We may or may not elect to detect conflict between player B's moves and player A's planned moves (actually, it's more complicated and probably not necessary.)
- Allow allies of player A to suggest moves to him while he's playing his turn. Overall idea is: player B moves one of A's units that he sees on screen, creating a planned moves. A then either immediately sees the suggested move (could be a pale line of the suggesting player's color, or something of the sort), or gets a prompt "suggested moves from player B are available", and he can then see a list of suggested moves, see what would their result on-screen be, and choose for each one to apply it (add them to his set of planned actions) or delete it.
- We can also allow the system to work in reverse, and allow the current player to see all moves that his allies are currently planning. This would be just amazing for coordination. Only caveat: we'll need to add the ability to filter some of that noise, otherwise the interface of players will definitely be too crowded.
- Add a way to show the attack choice and stats for already planned attacks, and to change the weapon used for that attack. Possibly show at the same time all attacks that are going to be executed on a single unit.
- (Very Difficult) Find some way of displaying the dialogues the current player sees to his allies (for instance the item choice screens from Bob's RPG era), but in a non-interactive way, so they can counsel him and again, be a bit less bored.
Calendar
Since I reworked the whole proposal, there's nothing to see here for now.