Advertisement

Game simulation combat

Started by April 24, 2021 04:26 PM
9 comments, last by Alberth 3 years, 6 months ago

Hey all

I wondering how to make a combat simulation like Grepolis/travian, where you got some stats on your troops and enemy troops, and when they fight, the simulation calculate both players soldiers stats, and then you get the result if you won and how many men you lost in the battle, so it's like a math calculator or something like that.

Any idea how to implement something like that or how to search for it? Haven't found anything yet to help, to were i start ?

Cheers!

You just describes exactly how to implement it!

  1. You define the input units.
  2. You run a battle simulation until some finish condition (time spent? #units dead or immobilized?)
  3. You read out the results.

Which part of this is your question about?

For the definition, you'd do it like for any game, actors with attributes.

For the simulation, you'd do it like for any game, stepping simulated time forward one tick at a time until the battle is done. Or, if this is a very-high-level simulation, simply compare “sum of attack of units” to “sum of defense of units” on the other side to calculate losses, apply losses, and iterate.

For the read-out, you'd do it like for any game; read values and display actors on the screen.

Is the problem how to “run the ticks until done” when there's not a main game loop and frame time?

Just pick a tick size, and run the simulation in a while() loop until you're done, incrementing game time by the fixed tick size for each loop – this will run much faster than real time if you don't involve any clock or display loop. Which is what you want!

enum Bool { True, False, FileNotFound };
Advertisement

The simplest simulations is playing a tabletop game, each party has their turns, each party has certain actions to perform and each party can roll some dice to confirm their actions and reactions

Simplistic example:

#!/usr/bin/env python3
import random

class Entity:
    def __init__(self, name, life_points):
        self.name = name
        self.life_points = life_points

def get_living(entities):
    return [entity for entity in entities if entity.life_points > 0]

def fight(entities):
    turn_num = 0
    while True:
        turn_num = turn_num + 1

        entities = get_living(entities) # Remove dead entities
        if len(entities) < 2:
            break # Fight is over!

        print()
        if turn_num == 1:
            print(f"Turn #{turn_num}.")
        else:
            print(f"Turn #{turn_num}, {len(entities)} entities still alive.")

        print("===========================================")
        for entity in entities:
            # Select an enemy.
            while True:
                enemy = random.choice(entities)
                # Don't hurt yourself.
                if enemy != entity:
                    break

            # Decide impact of the attack.
            impact = random.randrange(5, 15)

            # Output what happens.
            if impact < 8:
                print(f"{entity.name} kisses {enemy.name} with his sword.")
            elif impact < 11:
                print(f"{entity.name} hits {enemy.name} with his sword.")
            elif impact < 13:
                print(f"{entity.name} strikes {enemy.name} with his sword.")
            else:
                print(f"{entity.name} delivers a mighty blow to {enemy.name} with his sword.")

            enemy.life_points = enemy.life_points - impact

        # Some may have died.
        need_empty_line = True
        for entity in entities:
            if entity.life_points <= 0:
                if need_empty_line:
                    print()
                    need_empty_line = False
                print(f"{entity.name} has died.")

    print()
    print("===========================================")
    print("RESULT:")
    if len(entities) == 0:
        print("   All warriors have died, unfortunately.")
    else:
        print(f"   The winner is {entities[0].name} !!")


# Make some entities and let them fight.
entities = [
    Entity("Sworc the slayer", random.randrange(40, 70)),
    Entity("Quick Martish", random.randrange(30, 50)),
    Entity("Bolder the Tank", random.randrange(50, 60)),
]
fight(entities)

Output:

Turn #1.
===========================================
Sworc the slayer kisses Quick Martish with his sword.
Quick Martish delivers a mighty blow to Bolder the Tank with his sword.
Bolder the Tank kisses Quick Martish with his sword.

Turn #2, 3 warriors still alive.
===========================================
Sworc the slayer strikes Bolder the Tank with his sword.
Quick Martish delivers a mighty blow to Bolder the Tank with his sword.
Bolder the Tank kisses Quick Martish with his sword.

Turn #3, 3 warriors still alive.
===========================================
Sworc the slayer strikes Quick Martish with his sword.
Quick Martish kisses Bolder the Tank with his sword.
Bolder the Tank strikes Sworc the slayer with his sword.

Turn #4, 3 warriors still alive.
===========================================
Sworc the slayer strikes Quick Martish with his sword.
Quick Martish hits Sworc the slayer with his sword.
Bolder the Tank hits Quick Martish with his sword.

Quick Martish has died.

Turn #5, 2 warriors still alive.
===========================================
Sworc the slayer kisses Bolder the Tank with his sword.
Bolder the Tank strikes Sworc the slayer with his sword.

Turn #6, 2 warriors still alive.
===========================================
Sworc the slayer strikes Bolder the Tank with his sword.
Bolder the Tank hits Sworc the slayer with his sword.

Bolder the Tank has died.

===========================================
RESULT:
   The winner is Sworc the slayer !!

Some points to consider

  • All warriors have equal attacks
  • All warriors have equal defense (none, currently)
  • All warriors attack with a sword.
  • All warriors perform equally well against each opponent.
  • Warriors might attack already dead opponents (they are alive at the start of a turn, but could die on the first attack, and again on the second attack)
  • All warriors always get a turn (which may be good or bad depending on how you view balance of play)

@hplus0603 Thank you so much for explaining it abit for me, now i can move and see how i goes!

I properly got some more questions later on ?

But thx!

@Shaarigan Thanks for the suggestions ? I prefer my game to be in real time, like command & conquer etc etc. So it's properly getting harder to do that ?

Advertisement

@Alberth Thanks for taking so much time to that script. What i get from it, is that it's turn based? I would prefer real time like Age of Empires etc etc. Is that harder du implement?

trolle95 said:
Thanks for taking so much time to that script. What i get from it, is that it's turn based? I would prefer real time like Age of Empires etc etc. Is that harder du implement?

You could see the script as turn-based.

In real-time, a “turn” is passage of time, so a unit may move some, and possibly fire at the enemy if in range. Obviously, time progresses equally fast for each unit (hmm, would be fun if it didn't :p ), so again all units get an equal number of turns.

Don't under-estimate the amount of work in it though. To get a taste of the complexities in such a game, start fixing the things I mentioned.

Towards real-time, add position (in a simple grid), the option to move one cell (up/down/left/right) OR fight, and the requirement that you need to be in range of the enemy (for sword fighting, adjacent cells). You'll find this is already a lot to handle.

You may want to look into older games, like Dune 2 or the Command and Conqueror series.

@Alberth Thank you so much for explaining. I know it's a big project and will prob fail many times,
but i looking forward to the small milestones i set, so i'm still motivated ?

Right now i have tiles in my map and searching for the best system for the game. But a grid sounds good and easier to handle to movement, i guess you can combine a grid and tile right? ?

Cheers Trolle

trolle95 said:
Right now i have tiles in my map and searching for the best system for the game. But a grid sounds good and easier to handle to movement, i guess you can combine a grid and tile right? ?

Ha, that commonly works indeed, as all games have a limited set of equally large tiles :D

This topic is closed to new replies.

Advertisement