November 20, 2012 - Alpha details and a matter of originality
The client now connects to the server, downloads a list of games and then can connect to any individual game and begin interacting with the server, sending moves and updating the clients as the game progresses.
From a technical standpoint, the ‘netcode’ is fairly simple; when a client connects to a game, a snapshot of the game with all of the relevant data (position and status of units, players, whose turn it is etc etc) is delivered to the client which then sets the board up accordingly. The client then starts either polling via HTTP or listening via TCP (how this is chosen I have yet to decide) for new ‘actions’.
Actions represent every possible individual step which influences the game state in some way; a player joining or leaving during pregame, a unit moving, a new turn, a player being defeated or the game ending. Each action has both a timestamp and a consecutive action number. This means that all the client has to do is keep a record of which action number it’s up to, and wait for new actions. When new actions come through, the client processes these new actions in turn until it’s up to date with everyone else.
Because of the added complexity of creating a game which works over the Internet, some slight changes have crept into the gameplay, though these will be mitigated to keep the game as pure as possible. One such change is the way that individual units’ moves are processed.
In original Chaos, when you move a unit, after it has moved, it may then perform an attack (if it moves adjacent to a combat-capable enemy unit) or a ranged attack (if appropriate). These potentially up to three components of each unit’s ‘move’ are all typically linked together. With Archaos, a player may move their unit, and then lose connection, their PC may crash, the boss may come in – whatever – the point is they may be interrupted. In this case, with the traditional system there’d be two choices – either to automatically ‘end’ that unit’s move completely (which seems a tad unfair) or invalidate the unit’s move (not really practical).
The solution therefore is for the client and the server to track the move/attack/ranged attack phases as just that, distinct phases of the move. That way, if a unit moves but doesn’t get to perform its attack or ranged attack, clicking on it later in the same turn would allow you to continue its remaining phases.
Of course, this differs from Chaos and I’m always acutely aware of things which differ from what is both in my mind and the minds of most of its fans a well balanced and perfectly fine game. With that in mind, what I can do to ensure the gameplay remains (mostly) original is to automatically call the attack/ranged attack routine in the client after each unit’s movement phase. If the player then actively cancels one or both of these phases, they are marked as ‘complete’ and the unit’s move ends completely. Action or cancellation will be made mandatory on the client, so that the only time when the option to ‘revisit’ a unit will be available is if the move is cut short in some way. This does mean that players could potentially quit out of the game in order to bypass cancellation, but as there are no benefits I can see to doing so, it means that this feature can do its job without interrupting gameplay.
The game is now quite close to the alpha stage – that is it will be in some way playable very soon. The alpha will almost certainly begin by the end of this week, or the weekend at the latest (unless I run into some catastrophic game-breaking bug) and will feature a comparatively small subset of gameplay to begin with:
- Users will be creatable
- Games will be creatable (with the ability to set a width and height of the board – wizards will be spaced around the board as in the original game dependant on number of players)
- Games can have up to 8 players and can be limited to fewer players if the player wishes
- Players will be able to move units around the board, attack one another and cast basic creature units
- Players will be able to defeat other wizards and win the game
- Players will not be able to cast non-creature spells
- Wizards will not be able to mount creatures such as horses etc
- Animations for things such as spell casting, attacking, ranged attacking and wizard deaths will not be implemented at this stage
- There will be bugs, crashes and weirdness – this is an alpha remember!
I will make further announcements about the alpha during the week on Twitter. I will be looking for volunteers to help me test the game and iron out any issues with what is essentially the core gameplay mechanic. It won’t be a particularly amazing experience at this stage (not compared to the original game or the final product, or even the subsequent beta) but it will be essential to test it on a range of hardware, and in a range of conditions.
As Archaos is already multi-platform ready, I will be able to create iOS and Android builds for those alpha testers who would like to try it on their iPhones and iPads. If this is the case, I’ll provide further instructions on what you need to do to get Archaos running on those devices. I’ve not yet tested Archaos on Android but I will at some point this week before I start alpha.
If you’d like to be part of the alpha phase, and have read all of the above and realise that you’ll be testing a limited and unfinished product, leave a comment below or drop me a line on Twitter.
I can’t to try Archaos, but you already knew that!
On the issue of not being able to track combat moves after a disconnect, I had the exact same problem, but my work-around was different as I was transmitting the entire spell-selection/cast/move-list to the client, instead of the current state of the board.
The server should know if it hasn’t received an instruction to close the move-combat turn (creatures/wizards/shadow-wood turns with no rival neighbours should be automatically closed), so surely all is required, when a reconnect occurs, is to transmit some meta-information on the board state instructing the client on which pieces still require their move turn completing?
Apologies if this is confusing, or if I’ve mis-read the original problem, but I’d be happy to discuss it in further detail.
I really wish you’d taken your version further Andy – what I saw of it was absolutely fantastic!
I’ve opted for the ‘realtime’ route because I want to keep a sense that someone at the other end is moving the pieces around as you watch – it’s important for me that in a turn-based game, the pace and drama of the game is represented as closely as possible to what it’s like to play a tense hot-seat game. “Uh oh, he’s moving his vampire now…”
What I’ve implemented is pretty much as you’ve described it – the board state maintains the current status of each unit (moved, attacked and rangedAttacked each being flags that start each new turn as false) and each is represented by a different action (‘moved’, ‘attacked’ and ‘rangedattacked’) to place them chronologically and to describe the details (i.e. where the unit moved, who it attacked etc).
Ahh, I think I may have mis-read the original post, I thought there was a problem with tracking which moves had been ‘capped’, rather than disconnecting the move-attack-ranged-attack cycle.
Another gotcha I experienced with the movement cycle is when attempting to fly onto an enemy, thereby attacking, when already situated right next to the enemy (this assumes of course that the creature you’re moving isn’t engaged). This action, if unsuccessful would take up both the movement and attack phase, whereas my original assumption is that event though the movement fails I would still be able to initiate combat on the adjacent square.
I found myself poking values into a Spectrum snapshot to try out a lot of this stuff, just to make sure I was getting it right, which even with a disassembly is incredibly difficult.
I wondered if you’re chunking moves together, because my concern with a RESTful service is the latency issue. If you’re waiting on the server to receive a POST request each time you’re moving a non-flying creature, then it may take some time?
Yeah I recall what I assume to be a bug in that disengaged units can move-attack and then attack again once the game registers them as engaged. Whether or not it was intended I think it’s probably worth reproducing (although perhaps this is one of the less desirable bugs which may be configurable during pregame?)
Regarding latency and movement, currently the client awaits a response from the server before a move is performed, which will inevitably introduce a delay, however this will only be during testing as once all of the bugs and inconsistencies are worked out between client and server, the client should be able to be nearly 100% confident that a move can go ahead without needing to check it first, so the move will be performed in tandem with the move being sent to the server – if there’s inconsistency between the two then some error correction will have to take place – but if there’s any inconsistency then it can only really arise from a bug.
Also, in the case of non-flying units with >1 movement, the API ‘move’ endpoint accepts either a single co-ordinate or an array of co-ordinates. The client will be responsible for how those co-ordinates are generated (either individual moves a la original Chaos or a pathfinding system to interpolate the positions between start and end) and the server will then check the move to determine if it’s valid. In the alpha, movement will be done manually, and the client will send the whole move as an array of positions once the unit has expended its movement allowance or become engaged to another unit.
How about this for a bit of a creative solution: a random seed across all parties with a pseudo random number generator for combat, growth, and spell generation?
So this would remove the latency issue for the only person who would notice it, i.e. the local user.
I did a version previously with a seeded deterministic RNG though I think the animations will be sufficient to cover up the majority of the latency. If it proves to be an issue during testing then I’ll revisit it and re-implement the RNG using a unique seed (probably the unix time from when the game was created salted with some other hidden value) and an index based on the actions. I guess as long as the salt stays hidden, there’d be no easy way for people to ‘crack’ the RNG and predict the outcome of the game.