How to make a simple, rock-paper-scissors style combat?

I want to do a super simple combat system- I only really want to do this one fight scene, so I didn't want to do a full combat system, but after charting all the possibilities if I did it as a series of if/then's, I think there's got to be a simpler way to approach it.

a flow chart i put way too much effort into lmao

Basically, you and your opponent have the same five moves- Bite beats Smash, Smash beats Slam, Slam beats Bite. Blast and Shield beat all of the other three and Shield beats Blast. After you or your opponent use a move once, it's spent. You can't use it again in that fight. Winner is best three out of five. That's it. No health, no ammo, no multiple targets, it's as straightforward as I could manage.

So how would you go about turning this into a battle system? I can't seem to break out of the idea of just nested if/thens, it's all I'm good at lmao. There's got to be an easier way, I just can't think my way to it. Any suggestions?


To clarify. 1. Is this a 2-player game or is the computer one of the players? 2. If the computer is playing, is move selection random; 3. It seems the outcome can be a draw so do you want to play on until someone wins three moves or allow a draw after 5 moves?


I'd suggest making a function to handle each combat round.

To initiate combat, create attributes to hold the number of rounds won for the player and for the enemy; as well as lists of the moves remaining. And then call the combat function.

The combat function would prompt the player for their move, pick one for their opponent, and then compare the two. If somebody has won, do whatever comes next, otherwise call the function again.

So it could look something like:
Script to start combat:

game.combatWins = Split("Bite-Smash;Smash-Slam;Slam-Bite;Shield-Blast;Shield-Bite;Shield-Slam;Shield-Smash;Blast-Bite;Blast-Slam;Blast-Smash")
enemy_bob.combat_wins = 0
player.combat_wins = 0
CombatFunction()

And the contents of CombatFunction:

// Make sure that they all have a list of options (I assume the list refreshes in the case of too many ties)
if (not HasAttribute (player, "combat_options")) player.combat_options = Split("Bite;Slam;Smash;Shield;Blast")
if (ListCount (player.combat_options) = 0) player.combat_options = Split("Bite;Slam;Smash;Shield;Blast")
if (not HasAttribute (enemy_bob, "combat_options")) enemy_bob.combat_options = Split("Bite;Slam;Smash;Shield;Blast")
if (ListCount (enemy_bob.combat_options) = 0) enemy_bob.combat_options = Split("Bite;Slam;Smash;Shield;Blast")

combat_running = true
ShowMenu ("You are fighting Bob! Choose an option!", player.combat_options, false) {
  player_move = result
  enemy_move = PickOneString (enemy_bob.combat_options)
  list remove (player.combat_options, player_move)
  list remove (enemy_bob.combat_options, enemy_move)
  msg ("You used " + player_move + ". Bob used " + enemy_move + ".")
  if (ListContains (game.combatWins, player_move + "-" + enemy_move)) {
    msg ("You win this round!")
    player.combat_wins = player.combat_wins + 1
    if (player.combat_wins >= 3) {
      msg ("You won the combat! Congratulations!")
      combat_running = false
      // Do other stuff here
    }
  }
  else if (ListContains (game.combatWins, enemy_move + "-" + player_move)) {
    msg ("You lost this round!")
    enemy_bob.combat_wins = enemy_bob.combat_wins + 1
    if (enemy_bob.combat_wins >= 3) {
      msg ("Bob has defeated you.")
      combat_running = false
      // Do other stuff here
    }
  }
  if (combat_running) {
    msg ("You have won {player.combat_wins} rounds, and Bob has won {enemy_bob.combat_wins}. Ready for the next round!")
    CombatFunction()
  }
}

DavyB - It's single player, and initially the enemy's moves would have been scripted based on the players previous move, but it seems like random is a bit easier. Definitely would have wanted to keep going after a draw until somebody won. I hadn't really thought about draws. Maybe I can add something so when both players choose the same move, the move doesn't get removed from their list? That should make draws impossible unless they both end up with only the same move left on their lists, which maybe I'd just call a win for the player to avoid getting stuck.

MrAngel - Thank you, this is really great and straightforward! I haven't tried anything with creating functions yet and it was intimidating, but this is surprisingly easy to understand. I dropped it into a test game just to see how it works and it seems perfect. I'm going to test it out in my real game now and mess around with it. Thank you very much!


"Maybe I can add something so when both players choose the same move, the move doesn't get removed from their list?"
Sounds like a great solution!


So it's working great, and I did figure out how to make it so when they both choose the same move it just adds that move back to the list. Unfortunately, I can't figure out what to do when both the player and the enemy end up with the same move as the only move left on their list. They get stuck in an infinite loop and I don't know how to fix that. Any ideas?


Just call it a tie, and exit the battle loop with no winner.


Interesting, I didn't think of that possibility! The battle loop certainly has to stop when each participant has the same single move left. If the loop stops when one participant reaches a winning score of 3, it can only mean that the score is 2-2 when the problem occurs. If you don't want a draw, all you can do is restart.


You could also call the match when the first player hits 3 points.


So it's working great, and I did figure out how to make it so when they both choose the same move it just adds that move back to the list. Unfortunately, I can't figure out what to do when both the player and the enemy end up with the same move as the only move left on their list. They get stuck in an infinite loop and I don't know how to fix that. Any ideas?

That was why on the version I made, I didn't have special behaviour for ties and just said "if there are no moves left on the list, give them the full list back" … means the game can go on for as long as necessary until someone wins.


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums