Impractical code size requires more efficient sorting technique

  • (2 Pages)
  • +
  • 1
  • 2

21 Replies - 709 Views - Last Post: 06 September 2013 - 02:04 PM Rate Topic: -----

#1 JamesGE  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-September 13

Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 02:40 AM

Hi, I'm doing rudimentary work on a working on a hybrid D&D/strategy turn based-game. I am having a problem figuring out how to accomplish one aspect of it. I am a new python 3 programmer so it is an ambitious project.

In the game are many playable and non-playable characters, the total number of which could be up to around 60 depending on the level. Each character has a dictionary named with his/her name which contains all the character's attributes. At the start of a turn, each character generates an initiative score which is the sum of the character's initiative attribute value plus a random dice (d10) roll. What I want is for the highest initiative scoring character to be ranked 1st, and the progressively lower scoring characters to be ranked 2nd, 3rd, 4th, etc. This will allow me to have the highest scoring character act first, the second highest scoring character act second etc. I have done a workaround for this but as you will see below if I am doing this for 30, 40, 50, 60 or more chacracter the code will be waay too big. I need to find a way to do the same thing in a more compact way. If anyone has any ideas or suggestions or could turn me on to some processes that would help sove this I would appreciate it greatly.

    from random import randint      
    ish_roll = (randint(1,10)) #roll for character Ishido
    ish_tot= Ishido['i'] + ish_roll
    
    kent_roll = (randint(1,10)) #roll for character Kentaro
    kent_tot= Kentaro['i'] + kent_roll
    while kent_tot == ish_tot: #reroll if same as Ishido
        kent_roll = (randint(1,10))      
        kent_tot= Kentaro['i'] + kent_roll

    arren_roll = (randint(1,10)) #roll for character Arren
    arren_tot= Arren['i'] + arren_roll
    while arren_tot == kent_tot or ish_tot:
        arren_roll = (randint(1,10))      
        arren_tot= Arren['i'] + arren_roll

    roths_roll = (randint(1,10)) #roll for character Roths
    roths_tot= Roths['i'] + roths_roll
    while roths_tot == arren_tot or kent_tot or ish_tot:
        roths_roll = (randint(1,10))      
        roths_tot= Roths['i'] + roths_roll

    brig_roll = (randint(1,10)) #roll for character Brigand
    brig_tot= Brigand['i'] + brig_roll
    while brig_tot == roths_tot or arren_tot or kent_tot or ish_tot:
        brig_roll = (randint(1,10))      
        brig_tot= Brigand['i'] + brig_roll

    #what follows is the part not practical for many game characters
    
    if kent_tot >= ish_tot:
        kent_rank = 1
        ish_rank = 2
    else:
        kent_rank = 2
        ish_rank = 1

    if arren_tot >= kent_tot and ish_tot:
        arren_rank = 1
        kent_rank = kent_rank + 1
        ish_rank = ish_rank + 1
    elif arren_tot <= kent_tot and ish_tot:
        arren_rank = 3
    #and so on, which for 40-60 game characters, or less even, will be an enormous amount of code



I need to be able to accomplish the same thing, more or less, without needing to create a monster amount of code as will occur at the end of my code snippet.
Any help? Thanks.

Is This A Good Question/Topic? 0
  • +

Replies To: Impractical code size requires more efficient sorting technique

#2 JamesGE  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-September 13

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 03:16 AM

Actually, my working work around is actually this sorry, but it will nonetheless by waay too big with many game characters...
    if kent_tot >= ish_tot:
        first = Kentaro
        second = Ishido
    else:
        second = Kentaro
        first = Ishido

    if arren_tot >= kent_tot >= ish_tot:
        first = Arren
        second = Kentaro
        third = Ishido
    elif arren_tot >= ish_tot >= ish_tot:
        first = Arren
        second = Ishido
        third = Kentaro 
    #and so on, which for 40-60 game characters, or less even, will be an enormous amount of code


Was This Post Helpful? 0
  • +
  • -

#3 andrewsw  Icon User is offline

  • It's just been revoked!
  • member icon

Reputation: 3722
  • View blog
  • Posts: 12,990
  • Joined: 12-December 12

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 03:18 AM

First off: Have you studied Classes and object-oriented programming? Are you confident with dictionaries, lists, for loops?

If not, I would stop what you are doing and study the fundamentals of the language before attempting anything so ambitious.

Python the Hard Way

There is also a Tutorials link at the top of this page.

This post has been edited by andrewsw: 05 September 2013 - 03:20 AM

Was This Post Helpful? 0
  • +
  • -

#4 JamesGE  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-September 13

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 03:50 AM

Python the Hard Way starts by asking windows users to "run your terminal program" without saying how to do it or what it is. Internet search on the topic turned up nothing. Pardon my ignorance here. Anyway, that guide starts as a very confusing document, which is usually an indication to steer clear of it and look for another one that addresses more relevant, understandable things first.

I do not know about classes or object oriented programming so hopefully learning those will help me solve this problem.
Was This Post Helpful? 0
  • +
  • -

#5 andrewsw  Icon User is offline

  • It's just been revoked!
  • member icon

Reputation: 3722
  • View blog
  • Posts: 12,990
  • Joined: 12-December 12

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 04:02 AM

When you install Python it normally comes with a command-line (a terminal) where you can type Python statements, or a simple editor or IDE such as Idle.

I know a number of people have found that tutorial useful but, of course, it is not the only one. Some people mention codeacademy as useful but I have no experience with it myself.

This post has been edited by andrewsw: 05 September 2013 - 04:05 AM

Was This Post Helpful? 0
  • +
  • -

#6 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5901
  • View blog
  • Posts: 12,804
  • Joined: 16-October 07

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 04:03 AM

So, you essentially do this a lot:
roll = (randint(1,10))
tot= X['i'] + roll



Functions are your friends.

First pass:
def rollInit(mob):
	roll = randint(1,10)
	return mob['i'] + roll

def reroll(mob, alreadyRolled):
	roll = rollInit(mob)
	while roll in alreadyRolled:
		roll = rollInit(mob)
	return roll

ish_tot = rollInit(Ishido)
kent_tot = reroll(Kentaro, [ish_tot])
arren_tot = reroll(Arren, [ish_tot, kent_tot])
roths_tot = reroll(Roths, [ish_tot, kent_tot, arren_tot])
brig_roll = reroll(Brigand, [ish_tot, kent_tot, arren_tot,roths_tot])



The reroll thing is still damn messy. Order also seems impractical. What we want is a function that takes a list of characters and returns them in attack order. e.g.
mobs = getAttackOrder([Ishido, Kentaro, Arren, Roths, Brigand])



With what we currently have...
def getAttackOrder(mobs):
	order = []
	for mob in mobs:
		roll = rollInit(mob)
		while roll in order:
			roll = rollInit(mob)
		order.append(roll)
	# we now have an order of attack
	# we want to sort the mobs into that order
	# this is probably a little beyond you at this point
	# but it's how I'd do it and it will give you something to research
	
	# match up the order with the mob
	m = zip(order, mob)
	return [ y for (x,y) in sorted(m, key=lambda x:x[0]) ]



Anyway, that's one way to do it. Dictionaries are easy and you can do much with them, but you really want to look at classes. Imagine if each character has their own init method all you need only call that to get the value. And with that, certain mobs could have different rules for certain actions based on their type.

Hope this helps.
Was This Post Helpful? 0
  • +
  • -

#7 JamesGE  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-September 13

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 04:15 AM

Andrewsw, my python interpreter is IDLE, I have not encountered its command line function but will look into that. I will also try again with The Hard Way as I have seen it referenced many times and it does seem to have many chapters covering many things. Thanks.

Baavgai, thanks for your help! Yes it will take some time for me to decipher your solution but I have no doubt this will be very enlightening. Thanks.
Was This Post Helpful? 0
  • +
  • -

#8 JamesGE  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-September 13

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 04:24 AM

Baavgai, the messy reroll was obviously to make sure that no two opponents have a tied score, so that they are distinct from each other in the attack order. Does your code example accomplish the same thing? I won't be able to determine that myself yet, but it is still useful for me to know that your code does this as well.
Was This Post Helpful? 0
  • +
  • -

#9 JamesGE  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-September 13

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 04:33 AM

Ahh, I misunderstood you and now I can see where what I was referring to is occurring in your code....
Was This Post Helpful? 0
  • +
  • -

#10 andrewsw  Icon User is offline

  • It's just been revoked!
  • member icon

Reputation: 3722
  • View blog
  • Posts: 12,990
  • Joined: 12-December 12

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 04:37 AM

View PostJamesGE, on 05 September 2013 - 11:15 AM, said:

Andrewsw, my python interpreter is IDLE, I have not encountered its command line function but will look into that. I will also try again with The Hard Way as I have seen it referenced many times and it does seem to have many chapters covering many things. Thanks.

If you are already using Idle or some other editor then you shouldn't really need to revert to a command-line - unless you find it less confusing to do so. When a tutorial suggests typing:

>>> some_variable

in your editor just type:
print(some_variable)

and, of course, you need to save and run the file. This is, essentially, the main difference between command-line code and running a file.
Was This Post Helpful? 0
  • +
  • -

#11 woooee  Icon User is offline

  • D.I.C Head

Reputation: 25
  • View blog
  • Posts: 100
  • Joined: 21-November 12

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 08:42 AM

Quote

Actually, my working work around is actually this sorry, but it will nonetheless by waay too big with many game characters.
Store them in a list or dictionary, so instead of
if kent_tot >= ish_tot:
02	    first = Kentaro
03	    second = Ishido
04	else:
05	    second = Kentaro
06	    first = Ishido
07	 
08	if arren_tot >= kent_tot >= ish_tot:
09	    first = Arren
10	    second = Kentaro
11	    third = Ishido
12	elif arren_tot >= ish_tot >= ish_tot:
13	    first = Arren
14	    second = Ishido
15	    third = Kentaro 
You would sort the list, probably in reverse order, to get the result, what ever the number of players.
totals_list = [[29, "First Player"], [10, "I'm Second"], 
               [32, "Third Person"]]

sorted_list = sorted(totals_list, reverse=True)
print "The order of finish is"
for rec in sorted_list:
    print rec[1], rec[0] 

This post has been edited by woooee: 05 September 2013 - 08:44 AM

Was This Post Helpful? 0
  • +
  • -

#12 JamesGE  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-September 13

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 04:10 PM

As best as I can tell this displays the results in order but does not assign the characters an actual rank in the form of a variable or something, which is required in the next stage of the program to identify the character who is going to act first. If I work form your code...

Ishido = dict()
Ishido['i'] = 1
Ishido['name'] = 'Ishido'

Kentaro = dict()
Kentaro['i'] = 2
Kentaro['name'] = 'Kentaro'

Brigand = dict()
Brigand['i'] = 3
Brigand['name'] = 'Brigand'

ishtot = 7
kenttot = 12
brigtot = 4

totals_list = [[ishtot, Ishido], [kenttot, Kentaro], [brigtot, Brigand]]

sorted_list = sorted(totals_list, reverse=True)
print ("The order of finish is")
for rec in sorted_list:
    print (rec[1], rec[0])



I basically need to take the dictionary for the winner and do this

op1 = Kentaro

and then continue on with the others
op2 = Ishido
op3 = Brigand

I don't think your code did this, any suggestions?

This post has been edited by andrewsw: 05 September 2013 - 05:27 PM
Reason for edit:: Removed previous quote

Was This Post Helpful? 0
  • +
  • -

#13 woooee  Icon User is offline

  • D.I.C Head

Reputation: 25
  • View blog
  • Posts: 100
  • Joined: 21-November 12

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 06:59 PM

One dictionary will do the job. You can use either name or number as the key, pointing to a list containing the total and whichever was not used as the key. The total comes first in the list because it is simpler to sort in that format. The following code uses name as the key. To execute in greatest total to least total is the same as the print statement. If you want to execute in player number order then use a counter to get the correct record in the dictionary (easier if you use the number as key instead of the name) and increment by one each time, remembering to reset it to one once is becomes greater than the number of players, or loop through a list of names in the correct order again resetting to the beginning. Alternatively you can use an if() statement or a list to execute code in order.
from random import randrange

totals_dict = {}
## enumerate just increments a counter each time
for ctr, name in enumerate(['Ishido', 'Kentaro', 'Brigand']):
    totals_dict[name] = [0, ctr+1]

## add to the totals 5 times
for ctr in range(5):
    for name in totals_dict:
        score = randrange(1, 10)
        totals_dict[name][0] += score
        ## which is the same as
        ## name_list = totals_dict[name]
        ## name_list[0] += score
print totals_dict, "\n"

## returns a list of keys sorted by value, not by key
## or you can create a list if you understand that better
name_sorted = sorted(totals_dict, key=totals_dict.get, reverse=True)
for name in name_sorted:
    print totals_dict[name][1],  ## number
    print name,
    print totals_dict[name][0]  ## total score

## to execute different funtions you can use a list or an if statement
print "-"*50
print "Using an if statement"
for ctr, name in enumerate(name_sorted):
    print "%d, %-10s, %d" % (totals_dict[name][1], name, totals_dict[name][0])
    if 0 == ctr:
        print "     First place code here = op1"
    elif 1 == ctr:
        print "     Second code executed here = op2"
    elif 2 == ctr:
        print "     Third and last place here = op3"


def first():
    print "'first()' function"
def second():
    print "'second()' function"
def third():
    print "'third()' function"

print "-"*50
print "Using a List"
functions_list = [first, second, third]
for ctr, name in enumerate(name_sorted):
    print name,
    functions_list[ctr]() 

This post has been edited by woooee: 05 September 2013 - 07:10 PM

Was This Post Helpful? 0
  • +
  • -

#14 JamesGE  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-September 13

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 07:41 PM

Interesting, I will study this and see if I understand it.
Was This Post Helpful? 0
  • +
  • -

#15 JamesGE  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-September 13

Re: Impractical code size requires more efficient sorting technique

Posted 05 September 2013 - 11:19 PM

@baavgai
I think I've almost reasoned through your code. What a great example and help I've learned a lot just form this, thanks.

This post has been edited by andrewsw: 06 September 2013 - 01:58 AM
Reason for edit:: Removed large quote

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2