2012-11-14

(Programming) Thinking up a turn system. (Part 1)

To get something out of the way real quick, I think I monitor my words a little too much while typing.  I mean it's good to make sure things come out as intended, but...it's already a bit of a time eater on top of sharing things, which could be time spent working.  It's a silly thing to gripe over when there's so many other activities I spend time that feel wasteful.  Another point is when I monitor my speech I don't think I convey my words the way I'd like to anyway.  I see people out there with much more colorful ways of expressing themselves, and I look at myself and...well, I can only be me, right?  But no, it's something I can and should learn to change if I really feel the need to.  For now I'll try not to pause myself too much to write down what's on my mind.  However, I'd like to cut down on "things" and "stuff," among other things.

So I put up programming as a description for this blog, and...what programming "stuff" have I talked about anyway?  I don't fancy myself to be an individual of ideas; I'm merely going through the book to know more and hope it magically qualifies me for a job.  Awful.  What ever happened to going above and beyond?  At least I'm capable enough to follow a book.


So about that RPG I brought up before.  After the initial rush of writing up whatever I could to stuff in there it's finally slowed to a crawl.  Burst of inspiration then run out of fuel, a common pattern.  The same could be said for my initial desire to learn to draw.  I guess the main thing that's stopping me is teaching myself to make something that's interactive and not stuck in the console or simple text boxes.  Sure there's other things that need working on, but...yeah.  That's where my passion slammed headfirst into a wall.

Programming is largely about using preexisting code.  I think that's what they say.  And I suppose you'd have to balance using other people's code while also knowing how it works to an extent.  Which I'm not doing right now.  Instead of searching for other works I wanted to think it up.  It certainly won't work like that all the time.  Let's see what this slow mind thought up, then?

Initially (way back then) when I was playing with the battle system I had an 'if' statement for whether or not the player is faster than the enemy.  If so the player gets to execute the commands first followed by the enemy.  Otherwise...I copied the entire block of code and flipped it so the enemy could go first.  Pretty clunky, and soon after when I got the idea of facing multiple opponents or even having a party system it would be guaranteed to be really ugly.  The idea for a queue system crept up, but I didn't feel I was ready to read up on that section.  It's a shame; I probably would have had fun thinking up how to do it with the arrays I had, but that code will inevitably become a relic when replaced with a proper class.  Just like my old inventory system that would shift back for removed items.

A few weeks ago I returned to the game to tinker with the battle system after learning about queues.  What kind do I want?  This is where it would help to have a lot of exposure to the type of game you want to work on, but I've holed myself up too much.  Even then I'm surprised at the number of games I've played, but that's by my standard.

At first I thought of the Pokemon games.  Each participant gets a single move each turn, to be spent in an order determined by speed or priority modifiers.  No, let's not stop there!  How about people who can execute more actions than others?  Golden Sun (only played the first) came to mind with certain bosses who could attack twice in the time it takes all four party members to make a move.  Won't it be tougher on balancing?  Sure, but who needs to worry about balance in a non-competitive game like this.  Plus it would be fun to see how it could be broken, and if no one is around to play it to even find out as is likely the case, well, at least I didn't spend all that time tweaking it.  A corrupt thought process, perhaps.

A visible queue system like in Final Fantasy X would be awesome (where the idea first came to mind).  It even shows the impact actions would have on the list when you have certain stuff selected!


If I was clever I'd put something clever here.

I forgot it had purple bars.  Let's read into the game later.

Next source of influence came from the semi-roguelike Elona.  Nice, plain speed stat.  Plenty of freedom.  I don't know the inner workings of it but since it had an ingame clock I think you'd be running on "standard" time with a speed of 100.  If I was brave enough I'd ask the people who worked on porting it.  In Java, no less.

Okay, we have a turn-based battle involving people of various speeds, some who can take more turns than another.  The first thought was to include an initiative stat that starts at 0 and is modified by speed.  Let's say you have:

Player 1: Speed = 50
Player 2: Speed = 25         

The first turn passes and player 1 will have an initiative of 50, and player 2 with 25.  This is sort of done on paper in the program so it's still figuring out who gets a turn.  We'll have an 'if' statement to check if either player has an initiative of 100 (the turn's standard), and if so that player will be added to the queue and have their initiative reduced by 100.  If more than one player is eligible for being added to the queue we'll go by their initiative levels in descending order.  If any of them have matching initiative levels we'll break the tie by speed.  If their speed is tied we'll flip a coin/roll the dice or give preferential treatment to the player.  And if we want to be super nitpicky we'll have the system remember who won the coinflip and give it to the other party next time.

Let's try again:

Player 1: Speed = 200
Player 2: Speed = 150

We'll represent them in parentheses (player1, player2) which will display their initiative levels.  The player who gets to be added to the queue will have their name printed in front and their initiative level will be subtracted.  Initiative level must be greater than or equal to 100 to qualify for a turn.

(0, 0)

<Turn 1>

(200, 150)
Player 1 (100, 150) wins by initiative
Player 2 (100, 50) wins by initiative
Player 1 (0, 50)

<Turn 2>

(200, 200)
Player 1 (100, 200) wins by speed
Player 2 (100, 100) wins by initiative
Player 1 (0, 100) wins by speed
Player 2 (0, 0)

<Turn 3>

(200, 150)

And so on.


Now let's try something more extreme:

Player 1: Speed = 600
Player 2: Speed = 300

(0, 0)

<Turn 1>

(600, 300)
Player 1 (500, 300) wins by initiative
Player 1 (400, 300) wins by initiative
Player 1 (300, 300) wins by initiative
Player 1 (200, 300) wins by speed
Player 2 (200, 200) wins by initiative
Player 1 (100, 200) wins by speed
Player 2 (100, 100) wins by initiative
Player 1 (0, 100) wins by speed
Player 2 (0, 0)

Okay, at least player 1 gets twice as many moves in a turn but it's sort of bad to let so many of them be up front.  So I was stumped on this for a few minutes (those were some long minutes) wondering how I could get the distribution of turns to properly scale. 

All right then, if we're basing this off of how many actions someone can perform in a given turn then why not let the person with the fastest speed set the pace?  If we have someone with 600 speed then everyone (including the turn which runs at 100 speed) would have to reach that before they can do something.  So it's like executing mini turns inside the actual turn because of relative speeds.

Player 1: Speed = 600
Player 2: Speed = 400
Player 3: Speed = 100
Turn: "Speed" = 100

The standardized initiative level to perform an action is set to the highest speed: 600

We'll have the format as (player 1, player 2, player 3) - (turn)

(0, 0, 0) - (0)

<Turn 1 begins>

(600, 400, 100) - (100)
Player 1 (0, 400, 100) - (100)

(600, 800, 200) - (200)
Player 2 (600, 200, 200) - (200) wins by initiative
Player 1 (0, 200, 200) - (200)

(600, 600, 300) - (300)
Player 1 (0, 600, 300) - (300) wins by speed
Player 2 (0, 0, 300) - (300)

(600, 400, 400) - (400)
Player 1 (0, 400, 400) - (400)

(600, 800, 500) - (500)
Player 2 (600, 200, 500) - (500) wins by initiative
Player 1 (0, 200, 500) - (500)

(600, 600, 600) - (600)
Player 1 (0, 600, 600) - (600) wins by speed
Player 2 (0, 0, 600) - (600) wins by speed
Player 3 (0, 0, 0) - (600) wins by speed*

(0, 0, 0) - (0) turn completes  

<Turn 1 ends>

*For all purposes the turn will always be dead last when initiatives are tied, even if the
player is slower than it (would come into play over the course of multiple turns).

The spread looks better now, doesn't it?

Actually, the very, very first idea was to have a large counter of sorts incrementing all these values at different rates, but that's sounds more suitable for realtime stuff.  I guess this would be comparable to an imaginary race to cross a 100 meter lap as many times as possible in 10 seconds.  You have one going at 50 m/s, another at 20 m/s...they'll cover different distances after a second (or fractions of a second if we want a smooth motion).  The second, minute, and hour hand on a clock would work, too.  Why didn't I think of that earlier?  

Cutting it off here.  I didn't intend for it to be this lengthy but then those examples came up.  Perhaps I should reformat the blog to be wider or figure out how to create a text area with a scroll bar to save space.  A few more things come to mind to cover.  There's the case of initiative levels "spilling over" because the speed of the turn didn't divide evenly into the standardized initiative.  And what if the player with the highest speed dies somewhere in there?  I've thought about it briefly but haven't put it into code yet because I'm forever a slacker.  I should have some to share when I post the second part.
  

No comments:

Post a Comment