GSoC-WesnothWhiteboard Gabba

From The Battle for Wesnoth Wiki
Revision as of 06:29, 2 April 2010 by Gabba (talk | contribs) (Interface)


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/30/2010

IRC

gabba

About Me

See User:Gabba

History

To put things in context, this idea was already discussed in embryonic form

before it ended up as this formal GSoC proposal.

Credits

  • Boucman for introducing the idea of setting gotos when it's not your turn.
  • Crab_ for the overall concept and the backend mechanisms.

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.

Annoying gotos

Gotos (i.e. multi-turn moves) can be useful, but are also annoying since they are executed automatically at the beginning of your turn, and there's no visual display to show you at a glance which units have gotos set.

The Project

Overview

My project directly addresses the problems described above:

Waiting tedium and difficult allied planning (solution)

  • Instead of waiting, you'll be able to plan moves (and recruits, attacks, etc) while the others are playing.
  • If you have allies, a whole new dimension opens:
    • You'll see the moves of your currently playing ally as he plans them, and therefore will be able to comment on them before he commits them
    • Even better, he'll be able to see any moves you have planned for your turn, so you can finally coordinate that white mage placement or that attack correctly.

Conflicts between undo and various events (solution)

You'll be able to plan as many moves as you want, but unlike the current "undoable moves", they won't become "real" until you decide to:

  • Simply planning a moves triggers nothing. Shroud updates, WML events, ambushes and the like won't have the possibility of happening until you decide to commit a move.
  • When you commit a move and it does trigger an ambush, shroud update or WML event, your other planned moves will stay modifiable. The game will simply show you which of your remaining planned moves have become invalid because of the changing situation, so you can modify or replace them at your leisure.
  • Unlike undoable moves which must be undone in order, planned moves can be undone in any order, and commited individually in any order.
  • You'll also have the possibility of commiting all your planned moves in sequence; in this case, the game will stop commiting them as soon as another of your planned moves becomes invalid, so you can react to an unexpected situation.

Annoying gotos (solution)

No more self-executing gotos. You'll be able to plan multi-turn moves, they'll always be visible on the map (and to your allies), and the part that corresponds to the current turn will execute only when you decide to.

Interface

A little use case

Let's say it's the beginning of your turn. You select one of your elven archers, move your mouse around, and click a destination to move it to. Instead of your unit moving immediately, you'll see an arrow-terminated line showing the path your unit will take to get there, and a "ghost" (i.e. semi-transparent) form of the archer at the destination position. You repeat this with an elven fighter and a scout, and all three paths now show on the map.

Now, since you're playing as a team of two, you're not sure that the moves you picked will really benefit the team. You chat with your ally, and ask him "should I send my scout this way?". Fortunately, he sees on his screen the same arrows as you, and therefore the move you plan for the scout. "Sure", he answers. With renewed confidence, you hover the mouse over your elven scout and press 'c' to commit the move. The unit now really moves, and the arrow disappears.

Before committing the two other moves, you want some assurance that you'll have backup, since the orcs are charging at you across the plain. You ask your ally: "Can you move your white mage behind my archer and fighter?", and he agrees to do it. Even though it's not his turn, he selects his white mage and picks a destination for him, right next to your two units. You both see on your screens the path and the destination of the mage (on your screen his arrow shows in his team color); you now feel safer and decide to commit all moves. You select "commit all actions" from the context menu, and the game starts executing your remaining planned actions in the order you defined them.

The archer starts its move, but unfortunately it gets ambushed mid-way by a sneaky orcish assassin (you are playing the "Ambushing Assassin Era" :P). Since a special event happened, the game stops executing your moves. You decide to change the planned move of the fighter and attack the orcish assassin; since it's your last unit and you don't really need to plan the move before executing it, you shift-click to attack the orc, and the attack happens immediately. When his turn comes, your ally will probably also change the destination of his white mage.

Without depicting the scene frame by frame, the mockup below shows a tentative look for the interface elements necessary to realize this use case: file.php?mode=view&id=39500#.png

(Yes, I know that orcish assassins usually don't have ambush, but this one took courses from a renegade Elvish Ranger. Understood?)

  • Red arrows are planned moves for the current player, the blue arrow is a move planned by his ally.
  • Also notice the numbering, that corresponds to the order of programmed moves. The ally unit comes in last position since it's going to move on a later turn. (Displaying numbers in the little balls is cute, but if I do that I won't number units beyond one digit, i.e. beyond 9.)

Features

Disclaimer: all artistic details in this proposal, such as the display of arrows, numbers and the like, are subject to change.

Planning various actions

The player will be able to plan visually on the map all his actions (moves, attacks, recruits/recalls, dismisses) before "making them real", i.e. commiting them. He will also see on his map all planned moves from his allies who have shared them, and that he has elected to see. The display for those moves will be identical to his own moves, except they'll be clearly identified by the originating player's team color.

Moves and attacks

When the player selects a unit with movement points remaining, he'll see the usual thing as he moves his mouse, i.e. footsteps and the attack indicator to show attack possibilities. When he clicks to order an attack or a move, it won't be executed right away, but rather an arrow will be draw from the units current to its future position, and a "ghost" form of the unit will be drawn at the destination. If the action is an attack, the action indicator will remain to show the future attack. With several attacks planned, the display would look like this: file.php?mode=view&id=39499#.png

This image also shows a solution to display multiple moves/attacks planned for the same hex. Here: the two scouts that want to attack the orcish grunt from the same spot. We can't prevent the player from doing that, since he might have perfectly valid reasons to do so, such as repeatedly attacking a paladin with a horde of walking corpses from the only available hex.

Recruit/Recall

A ghost of the soon-to-be-recruited/recalled unit will appear at the same spot it usually would; various visual clues are being considered to indicate the planned move status.

  • A good question is whether to visually decrement the player's gold (without touching the backend value) when that happen; it would probably be a good idea, so he can count up how many units he can afford before confirming the recruits/recalls.
Dismiss

The best way to display a planned dismiss is not determined yet. Ideas include:

  • Display a black shadow where the unit was previously; but what to do if another unit subsequently moves in the same hex?
  • Provide a list of dismissed units, from which you can make them come back if their original location is free and no conflicting change to the game state happened.

Conflicts and their display

The game will check ally actions for validity whenever they are planned. They will also be re-checked for this after any modification to the planned moves, or after commiting a move (which might trigger an ambush or a game-altering WML event). Two kind of conflicts can be detected by this validity check:

  • Conflict between two planned actions: any action

Commiting moves

Undoing and manipulating planned actions

Instead of storing a general undo stack, allowing you to only undo the last action, undo will be per-unit. By selecting undo from the context menu of a unit or hitting 'u' while it's selected, you'll cancel the planned action of that unit.

  • move/attack: the ghost form, arrow and attack indicator just disappear
  • recruit: the unit will disappear -- note that if the unit has random traits

However, once a move is commited, there will be no way of undoing it.

At the end of the turn, all the player's unused planned moves and therefore all his undo possibilities will be deleted. A dialog box asking "You still have planned moves, are you sure you want to end your turn?" might be necessary.

See ally planned actions

Summary of commands

(Subject to change)

Options

Mockups for various interface elements

An alternate display for the numbering of planned moves

file.php?mode=view&id=39503&sid=351c6863d85dce6d56e131736224b471#.png



Highlight planned path on select or mouseover

file.php?mode=view&id=39504&sid=351c6863d85dce6d56e131736224b471#.png


Variants and experiments on the numbering system

The double/triple digits "overlay" display of number seems to work ok (three-digit might need to be placed in upper-half of hex to avoid completely hiding middle digit), file.php?id=39520&mode=view#.png

especially with brief flashing of the number on top of a unit when this unit is hovered over or selected. file.php?mode=view&id=39521&sid=bb7ee496abdc777856a391f020f2d084#.png

Alternative: simply show the number next to units. Less disruptive visually maybe? file.php?mode=view&id=39524&sid=bb7ee496abdc777856a391f020f2d084#.png
.
.
.
.
.
.
UNDER CONSTRUCTION
.
.
.
.
.
.

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 to the game engine

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. 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 to 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 (network::send_data()) 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.

Sequence diagram showing the exchange of data

file.php?mode=view&id=39528&sid=ac6e69cd642b2e878b0bf71b38fa38e5#.png

ZOC calculations for planned moves

The "show enemy moves" feature will now be calculated from planned unit positions by default, instead of current unit positions. For this I'll need to build my own unit map and calculate ZOCs from there. When several moves are planned for the same spot, only the last one to be programmed will be taken into account; this will have an influence when ZOC-less and normal units are heading for the same hex.

Raw Design Notes

The following are the design notes I haven't organized yet. Nothing to see here people.

TASKLIST

  • Polish and proofread proposal
  • Add tasklist+timeline
  • Upload code samples to About Me page
  • Add examples of code/proof-of-concept code to this page

FEATURES

  • Need a way to change order of planned moves:
    • Keys/menu items to bump a unit up/down the list
    • Should units given a new planned action lose their place in the action queue and be bumped to the end? Probably not, as it would get annoying when you just one to move the destination by one hex.
  • Detect conflict between player B's moves and player A's planned moves. (We'd need to differentiate "impossible" moves from "possibly hindered by own or allied unit" --> interface complication.)
  • Options to filter vision and sharing of ally moves
  • How to deal with displaying a lot of undo info: for instance player moves and then dissmisses his unit? We could keep and individual per-unit undo stack or sorts in the planned_actions vector, but it seems better to just allow one planned move per unit.

OPTIONAL/FUTURE DEVELOPMENTS

  • 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.
  • 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.
  • Might be useful (if not too hard to use), to allow to make assumptions about enemy units. e.g., "what will zoc look like if that, that, and that enemy units are dead ?"
    • auto-assume that units, say, with >80% ctk will be dead ???
  • (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.