The First-Approach Problem


It’s time for another devlog!

For the last few days, I’ve been rewriting how the game handles the events caused by using a skill, since the old system required a lot of repetition and hardcoding new features. Here’s a comparison of how the Twister skill was handled, then and now:

OLD

[name] Twister
[description] Attack all adjacent units. Push them away.
[effect1] directional_attack 0 -1
[effect2] directional_execute 0 -1 attempted_move 0 -1
[effect3] directional_attack 1 -1
[effect4] directional_execute 1 -1 attempted_move 1 -1
[effect5] directional_attack 1 0
[effect6] directional_execute 1 0 attempted_move 1 0
[effect7] directional_attack 1 1
[effect8] directional_execute 1 1 attempted_move 1 1
[effect9] directional_attack 0 1
[effect10] directional_execute 0 1 attempted_move 0 1
[effect11] directional_attack -1 1
[effect12] directional_execute -1 1 attempted_move -1 1
[effect13] directional_attack -1 0
[effect14] directional_execute -1 0 attempted_move -1 0
[effect15] directional_attack -1 -1
[effect16] directional_execute -1 -1 attempted_move -1 -1

NEW

[name] Twister
[description] Attack all adjacent units. Push them away.
[effects] P.targets = adjacent: P.user
U.targets = occupants: P.targets
foreach: U.target, U.targets
  P.target = at: U.target
  animate: slice, P.target
  attack: U.user, U.target
  D.push = from: P.user, P.target
  P.destination = to: P.target, D.push
  move: U.target, P.destination
end

The new effects use a language I made up for this purpose, called SkillScript. It’s far from the best language, but it’s a lot more flexible than that ridiculous stuff I had to do before with directional_attack and directional_execute, both of which were hacks anyway.

(As a side note, when I get an error in SkillScript, I call it a “skill issue”.)




Anyway, this new SkillScript system is not actually the point of this devlog. It’s good that I got it done, but I was really procrastinating on trying to solve a different problem. This one is a fundamental design flaw of the game that I was aware of before even releasing the demo. It is…

The First-Approach Problem

(...or at least, that’s what I’m calling it.)

I went over this briefly in my v0.1 retrospective. Consider a golem and an enemy - each knowing Step and Strike - standing one tile apart:

For both characters, the intuitive thing to do is to move closer to your opponent so you can use Strike on them next turn. But if you do that, they get to use Strike on you first, and (at least in the image above) you’ll die.

So maybe a better strategy is to hang back and wait for your opponent to come close. But if both characters do that, then they get stuck in a stalemate forever.

As for what happens in the actual game: the enemies are too dumb to realize they shouldn’t approach, so the best strategy is for the player to wait for the enemies to come to them. This is bad game design for a couple of reasons:

- It’s boring

- It expects the player to know the AI’s flaws

This problem wouldn’t be so bad… except for the fact that almost every character in the game uses the basic Step/Strike skillset, or some variant of it. Here’s a chart to show just how common it is:

(Note: A lot of creatures in the “other” category still suffer from this problem, since they know skills that are similar to Step and Strike. For example, the Dust Bunny knows Dash and Shove.)

This issue is bad enough in normal situations… but it also has a side effect. If you can attack an enemy and then create a gap between you, the enemy won’t be able to counterattack. It will walk towards you again on its next turn, letting you hit it again, make a gap again, and so on. This strategy can be easily achieved using the following skills:

- Shove: Attack an adjacent unit. Push it away.

- Twister: Attack all adjacent units. Push them away.

- Telekinesis: Force any unit to move to an adjacent tile. (Attack the enemy, then have another golem force it away with Telekinesis.)

- Overclock: Pick a unit. If it has acted this turn, it may act again. (Attack the enemy, then use Overclock on the attacker and have it step back.)

In my experience - and the experience of a few playtesters - this makes Telekinesis and Overclock “must-pick” skills, and by extension, Mu and Jolt are “must-pick” golems. I haven’t noticed this with Shove, Twister, or Pamml, though - maybe that’s because you can’t push a unit away unless there’s room, so it’s less reliable? In any case, roguelike games are usually not interesting when there’s one “best strategy” you can go for every time. So, I really need to look into changing this.

Solutions

In my head, I’ve gone over some ways I might fix this. A few involve pretty significant changes to the game’s design, but I’m not against doing that, provided it actually makes the game better.

A) Diversify skills. Give more units other movement/attack skills instead of Step and Strike.

Pros:

  • Makes game more interesting
  • Doesn’t change fundamental design

Cons:

  • Might be confusing to not know how enemies move or attack without checking skills
  • I don’t have a lot of ideas for other attack/movement types

Assessment: This is probably something I’ll want to do anyway, but it might not be enough to fix the First-Approach problem on its own.

B) Allow each unit to use all its skills once each turn, instead of only one skill per turn.

Pros:

  • Player turns feel more impactful
  • More decisions to make about what moves to use & when
  • Encourages rushing enemies more (rather than waiting around)

Cons:

  • Overclock would be even more broken (assuming it restores all skills)
  • Enemies might be harder to predict, leading to unfair-feeling defeats
  • Doesn’t completely solve the problem (the danger zone around a unit would be two tiles away, instead of one)
  • Game tree gets exponentially bigger, making it harder to code the AI

Assessment: This is a little out of left field, but I actually quite like it, at least in theory. It’s something you don’t see in a lot of games and I think it might help a lot.

C) Each unit gets a mana count. Mana is refilled each turn. Using a skill costs 1 mana.

Pros:

  • Player turns feel more impactful
  • More decisions to make about what moves to use & when
  • Encourages rushing enemies more (rather than waiting around)
  • Adds more variety between units (since they have different mana counts)
  • Interesting interaction possibilities (e.g. there could be a skill that reduces enemies’ mana)

Cons:

  • Board & UI get more cluttered to display mana count
  • Game becomes more complicated to learn
  • Enemies might be harder to predict, leading to unfair-feeling defeats
  • Doesn’t completely solve the problem (the danger zone around a unit would be equal to its mana)
  • Game tree gets exponentially bigger, making it harder to code the AI

Assessment: I initially thought this would be too complicated, but I started to like it more as I wrote out the list of pros. It’s similar to the above “use all skills” idea in that it allows more actions per turn.

So, what’s the plan? Well, I like the sound of the last two ideas, but the only way to know how they’ll go is to try them out. I’ll do the “use all skills” option first (since it’s a lot easier to code than the mana thing) and see what the game feels like to play!

---------------------------

Alright, after a bit of finicking around with the code (the previous enemy turn function was really not designed for this), I have implemented option #2! Any unit may now use all of its skills in one turn, instead of just one. I played a run with this, and here are my thoughts…

The game feels harder now, but I think that’s because it was too easy before. Previously, you could usually avoid all damage with carefully planned movements. Now, you’ll often have to weather a few hits to make it through. It definitely feels more like the player is the one going on the offensive, rather than waiting around for the enemies to come to them, which I think is a very positive change. (For example, with Bolt, you can sometimes dash forward and kill an enemy on the first turn.)

I was able to win a run without too much trouble once I got going, but I lost a couple of attempts early on, mainly because of Dust Devils. (They were already strong to begin with, and giving them more actions per turn made them even stronger.) I might want to nerf their attack from 2 to 1? Alternatively, I could tweak the “difficulty budgeting” for encounters, so they won’t appear so soon.

Speaking of nerfing, though, there’s one more thing I need to take care of.

Original meme here.

Nobody likes when their game-winning strategy gets nerfed… but in this case, it has to be done.

This nerf isn’t as harsh as it seems. Jolt knows Overclock and Step, and it’s now allowed to use both in the same turn, so it can follow another golem to keep refreshing it. The main challenge will be keeping it safe.

There are other things I want to rebalance, too. Some enemies - like Vipers or Dust Devils - have become much stronger, and they probably shouldn’t appear too soon or the player will be overwhelmed. In addition, the first solution I mentioned - “diversify skills” - is something I also want to work on. I’ll do this largely by adding new golems and enemies, so be on the lookout for those in the next update!

Here’s a preview, featuring a nerf and a new enemy.

(Note: these enemies and their stats are still subject to change.)

Conclusion

This new version will feel a lot different to play, but I think it’ll be a positive change overall! I’m looking forward to seeing what people think of the skill-usage changes and the new content.

This devlog was delayed by a few days because I was busy with this year’s GMTK Game Jam. My submission, A Tight Fit, is a small but challenging puzzle game about changing blocks’ size. Give it a try if you’re interested!

As always, thanks for reading!

Get Golemancer

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.