Dev Log 4: Surprise and Trap MechanicsStill recovering from surgery, I decided to use my first week back at programming to work on something light before diving into multiplayer code. Well, as the rule of software engineering goes, when a programmer believes a task will be easy, they are more often than not "surprised" to find the task is much more involved than expected. How appropriate that I should be so surprised working on the "Surprise and Trap" game mechanics.
What is a Surprise Mechanic?In Summoners Fate, a Surprise is a card played with its target and effects hidden from the opponent until they are triggered by a game condition. This mechanic opens up a whole new catalogue of strategies for the more sneaky inclined players, such as placing hidden traps on the board that spring when the player's character walks over them. Traps were one of the most requested "abilities" from my players in Hero Mages, Summoners Fate's predecessor, so of course this time around, I aimed to deliver the feature.
Here is a video from the article where the AI-controlled Summoner casts a surprise Ice Trap, then they use their knockback ability to push my gladiator into it, taking advantage of the trap's effect during their turn. Note: the "surprise" card art icon is placeholder.More than traps, Surprises are also a way to incorporate a common CCG mechanic known as an "interrupt" into an asynchronous turn-based game. Generally, interrupts are played by during an opponent's turn when they are attempting to do something (for example cast a spell) and you want to interrupt the action, say with a counterspell to stop that spell from happening. Since live interruption is impossible when you are playing a game asynchronously, one way to solve this is to premeditate the interrupt with a conditional effect. In Summoners Fate, counterspell is achieved by placing a hidden status effect on your caster. It has a condition "When enemy casts a spell, counter it". In this way, the game automatically interrupts your opponent on their turn, whether you are actively connected to their game or not.
Programming SurprisesThe architecture of Summoners Fate supports surprise mechanics with the following structure:
1.
Cards contain an
action that performs any number of action effects. One type of action effect can affix a status effect to an object (unit or space on board)
2.
Status effects can contain 1 or more attributes (modifiers to basic stats such as attack power or life) as well as any number of triggered abilities
3.
Triggered abilities are actions that can respond to events and can have any number of conditions that must be true before executing the action's effect
4.
Events are messages fired by the game when something happens, such as a unit entering a position or a spell being cast.
To program a surprise card, I write an action that affixed a status effect containing a trigger for a desired condition (such as when enemy casts spell) and executes desired effect. I do this using the definitions editor I wrote for the game. Pretty straight forward, right?
To make development easier, I created a tool for programming triggered abilities. It includes a "cheat sheet" that identifies what each event property maps to so I don't have to memorize all the permutations.Well, that's what I thought until I started to unfold all the possible user-facing considerations about what a Surprise flow actually entailed.
Design ConsiderationsThe first major design question I had was: When a surprise is played, what exactly happens? Is the opponent informed that a surprise has been played or do they not see anything until it the surprise triggers? How this question is answered has major implications on the player experience, including the perceived fun and fairness of the mechanic.
I spent a lot of time discussing this with players. Not showing the player anything at the time a surprise is played has the perception of a more "hardcore" experience, where players must rely on very subtle clues in the player's behavior (ex: not appearing to cast any spells on their turn, moving their units in odd patterns, etc.) to suspect there may be a surprise. On the other hand, showing a warning "Surprise has been cast!" creates immediate excitement and tension at the cost of losing a small element of the surprise. All agreed that only in practice can we really uncover what the experience will feel like, so it made sense to proceed programming the early warning system, with an option to turn this off during playtesting to try both options.
The next question, how are surprises tracked/stored? Well, it makes sense that traps placed on the board would naturally have markers indicating them. But, only the player who created the trap should see it, while the other player shouldn't see anything until revealed. For surprises attached to units, such as when a unit is attacked, do X, it made sense to store as effects on the unit's card, viewable when examining that card (but only visible to the creator of the surprise).
The complexity of how these items can be stored and tracked by the player suggested to me that there should be only 1 surprise allowed per target. It doesn't make sense to place multiple traps on the same tile if I can only effectively show 1 marker per tile. Interestingly, this also creates side mechanic for revealing/disarming traps where a player might try and place a trap on a tile already trapped by the opponent. Doing so would replace the existing surprise with a new one, ensuring to the placer of the new surprise that there isn't an additional surprise waiting on that tile and indicating to the placer of the old surprise that their opponent has played something on that spot.
Surprise User FlowTo help determine the list of tasks necessary to program the feature, I started by writing what the user flow looks like when a surprise is played:
To read more, click here.