0
\$\begingroup\$

This is more like a mathematical problem, but I guess this is the best place to ask it.

I am working on a PVP concept and I have the following problem. There is a "battle" between two players that both have set their moves before the match starts. So, during the battle, they just watch the screen and text describing the events.

This battle takes 30 min and attacking/defending text events are appearing during this time. In average, I have about 5 main events and 3 secondary events. When the battle start, the code is aware of the number of main events, but not the secondary. They are calculated on the fly.

The process is like,

newEventTime = previousEventTime + formulaForRandomTimeInterval

What I try to do is to build that formula and avoid having big empty time gaps on the battle and also avoid having a lot of them in a small period.

Also, I want to have slightly more events as the time pass to increase the interest.

Was thinking something such as:

formulaForRandomTimeInterval = (battle_time*2/main_events)*random(0,1)

where battle_time = 30 and main_events the number for that battle.

Any idea for a better solution?

Edit

Sorry for the confusion. Here are a couple of more details about it.

An example of events:

  1. At 3' Player A attacked and made 45 damage. (Main event)
  2. At 8' Player B attacked with a sword and made 110 damage. (Main event)
  3. At 12' the weather changed and started raining. Both players had issues with the mud. (Secondary event)
  4. At 19' Player A made a move but player B dodged the attack. (Main event) ... ...

There is another part of the code that decide which event will be the next and what exactly would be. The battle will be over only when the main events are finished. As I said, each battle has different number of main events of average 5, but the code know this number as the battle starts. But doesn't know the number of secondary events which are created by random.

So, when the code does the loop on the events and decide the type of the next event, the time code is called to decide in what minute it will be appeared.

\$\endgroup\$
  • \$\begingroup\$ How much output is there for each event? How dense is the information? What makes the information relevant to the player at the time of display? Is the player being notified, enabling afk during the events? Why exactly would the player watch the screen for half an hour without the option to interact? Wouldn't the player just start the battle, leave, and read the log or results after it's all over? \$\endgroup\$ – Estharon Aug 23 '16 at 13:05
  • \$\begingroup\$ Reflecting on my comment, only questions 1, 2, and 4 are relevant for an answer, the others are mainly for you to consider. I was (until I got carried away) trying to find out if we're talking about messages like "outer wall taken", or a 4x7 table of complex strategic information that needs time to process mentally. That would make a great difference for the pacing. \$\endgroup\$ – Estharon Aug 23 '16 at 19:15
  • \$\begingroup\$ @Estharon sorry for he confusion. I edited my question with an example and a few more details. \$\endgroup\$ – Tasos Aug 23 '16 at 21:19
1
\$\begingroup\$

Before we start: Why does the code not know the random events beforehand? Without interaction, couldn't you just as well calculate them in advance without any difference in the player's experience? And if their effects affect the battle, how can you know the number of main events without knowing the impact of random events? Ah, I probably don't need that part of the picture, so let's get started with the mathing.


This is a math question at first glance, but there's more to it than that. I would factor the nature of events into determining their frequency.

What I gather from your examples is that there are basically turn-based actions and random (environmental) effects. These two are different concepts that depend on different factors, so the player will have different expectations as to when they happen. There is also a different impact of the effects based on when they happen.

The frequency of turn-based actions should be related to the abilities of the character. It would make little sense for the same sword attack to take twice as long as usual because it is starting to rain, and then take the normal time while it's still raining. The battle speeding up bit by bit makes sense, and reflects the growing desperation and determination to win before running out of strength or getting killed yourself. Speeding the battle up means we have higher action density towards the end of the battle.

Random events happen, well, randomly. The player will have very few expectations here, except maybe a reasonable distance between events like weather changes. But nobody would be surprised if, a minute after it starts raining, a wild boar charges out of the nearby woods. This means you have a lot more freedom with the random events. However, in order to affect the battle, they would have to happen early.

This is quite fortunate. We can have random events happen mostly in the first half of the battle, while the constant acceleration pushes attacks into the second half. In other words, accelerating the turn-based actions opens a time window for the random events.


My solution would be to implement two timelines:

Turn-based actions happen in a mostly uniform fashion, each action up to 10-20% faster than the previous. That allows you to add up the factors and scale them against the total.

Random events mostly happen in the larger time spans at the beginning of the battle. You can time them to be 1/3 to 2/3 of the way to the next event for a randomized but even distribution. Sometimes they do happen between the shorter turns at the end, but I'd keep the probability for that low, maybe by scaling effect probability with duration of the next action.

I would avoid using the loop to calculate time, but rather calculate all beforehand and just check the system time to see if it's time to display the next event. That saves cpu usage if the game is running on a device that is multitasking, even if it's just a few cycles.


Let's start with the turn-based actions:

Calculate duration modifiers, get each by randomly modifying the previous one
Using ~20% and 6 actions for a more visible effect here
Example random duration modifiers of 6 turn-based actions:

D0=0, D1=1, D2=0.8, D3=0.72, D4=0.67, D5=0.55

calculate the sum of all duration modifiers up to the
current modifier to get the timestamp modifier

T0=0, T1=1, T2=1.8, T3=2.52, T4=3.19, T5=3.74

Scaling towards the desired total time:

Total time is proportional to the last modifier.
Divide total time by it to get the time scale factor

1800sec/3.74 = 481,28sec (whatever precision you need)

Multiply each time modifier with the time factor to get the time its event happens

Ex.: T3 = 2.52 x 481,28 = 1212sec = Minute 20 (:12sec)

Each of these sets of calculations fit nicely into a for loop handling an array.

Now to designate a time to the random events. We shift the probability towards the beginning of the battle to balance against acceleration. I'll show two samples for comparison

Do this whenever you display a turn-based action :

Get the duration modifier of the next action

T1.next = D2 = 0.8
T4.next = D5 = 0.55

Square the number to shift the probability to the early battle. These are your probability modifiers.

P1 = 0.8^2 = 0.64 chance for random event to occur between T1 and T2
P4 = 0.55^2 = 0.3025 chance for random event to occur between T4 and T5

...maybe use 3rd or higher power to increase the difference
and make late effects something 0.1-ish...

In case of a random event,
place it halfway to the next turn-based action, +/- 1/3.

Disclaimer: This is by no means balanced, but demonstrates a way to push events between others while maintaining a relative scale of time between events and might be a starting point for your own design.

\$\endgroup\$
  • \$\begingroup\$ I think this is really close to what I need to start working on it! It is awesome. I will upvote both answers since both helped me, but I will choose this one since it was focused on maths and gave a nice idea of how it should work. \$\endgroup\$ – Tasos Aug 24 '16 at 10:17
  • \$\begingroup\$ Ironically, I got the inspiration when I ignored numbers for a moment and looked at things in a perspective of world building, player experience, and strategy. Thanks for the pick, glad I could help. \$\endgroup\$ – Estharon Aug 24 '16 at 10:43
3
\$\begingroup\$

I share the skepticism @Estharon expresses about whether players will enjoy a 30-minute non-interactive battle, but I'll answer as if it's a given that these will be interesting events.

Unless there's a compelling reason for this to take exactly 30 minutes, I would make a sequence of smaller fixed or randomized decisions (balanced around a target duration) as the battle plays out rather than trying to pick times before the battle starts without complete knowledge of the events or of how slow/fast the player reads.

Consider a few basic mechanics along these lines:

  • The battle has a variable current_intensity
  • Each individual event has its own (appropriate) fixed intensity and effect_on_battle_intensity
  • Each event could have a set duration and message frequency, though I would probably just have a simple format for writing out template lines and a delay before the next message (in which case duration is just a sum). The latter would let you mix messages of differing lengths a little more effectively, while the former would require writing messages that stay within a smaller range of what the player can keep up with.
  • Rather than try to select events more frequently towards the end of the battle, you select more intense (dense/verbose/dramatic) events as the intensity of the fight rises
  • Skew either the event pool or the event selector towards events that increase intensity (probably just a 10-35% chance or so of an intensity-reducing event)
  • When one event ends, explicitly choose a tolerable delay before starting the next event (random, fixed, or based on the duration of the ending event)
  • The battle has a fixed or random terminal intensity that, once exceeded, will select an event from a pool of battle-terminating events

This would let you cobble together a varied action sequence from well-planned events with reasonably small interruptions. The sequence can have a sense of rising action to some terminal event. It also builds in several levers that you can play with to make the experience more variable. If the players don't have any leveling mechanism, you could just have 5 or 10 intensity levels and start the battle at 1. If players can level up, the start and terminal intensities can depend on player levels.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.