-4

I have the following code and am trying to make it shorter. I've tried using while and for loops but cannot make it work. I've also searched here at Stackoverflow and found enumerate and cycle loops, but keep on getting errors or generally don't know what I'm doing. Are there any ways to shorten this?

I'm sing python 3.2 with pygame-compatible version and idlex.

players = [npc1,npc2,npc3,human]  # these are classes

# sets new order of players after being mixed   
first_player = players[0]
second_player = players[1]
third_player = players[2]
fourth_player = players[3]

# sets players prey...goes one ahead in the index, wrap around at end
first_players_prey = players[1]
second_players_prey = players[2]
third_players_prey = players[3]
fourth_players_prey = players[0]

# sets players predator, goes back one in the index, wrap around
first_players_predator = players[3]
second_players_predator = players[0]
third_players_predator = players[1]
fourth_players_predator = players[2]

# sets players grand prey/predator while only 4 players, goes 2 ahead/back in index, wrap around
first_players_grand_prey_predator = players[2]
second_players_grand_prey_predator = players[3]
third_players_grand_prey_predator = players[0]
fourth_players_grand_prey_predator = players[1]
George Willcox
  • 677
  • 12
  • 30

2 Answers2

0

Although unconventional, the exec function can be used to accomplish what you're after. (I'm not too good at Python yet, there's probably a better way) I used a similar approach in a class that I've written. A list can hold the values of first though to fourth, and then the names of the different roles. This can be used to then recreate your code in just a few lines.

numbers = ['first', 'second', 'third', 'fourth']
roles   = ['', '_prey', '_predator', '_grand_prey_predator']
values  = [0, 1, 2, 3]

for i in range(4):
    for j in range(4):
        exec(numbers[j] + '_player' + roles[i] + ' = players[' + str(values[j]) + ']')
    values = values[1:4] + values[:1]

I hope this answers your question.

George Willcox
  • 677
  • 12
  • 30
  • If you create a new python file, paste this code in and change exec to print you'll see how it works – George Willcox Dec 09 '16 at 22:18
  • 1
    Remember that using the `exec` is _["significantly slower than simply calling regular Python code" and it's strongly urged you never use it](https://late.am/post/2012/04/30/the-exec-statement-and-a-python-mystery.html)_. It also could potentially be dangerous to use if it ever would execute input from a user. The interpreter won't detect the names either so all code has to be remembered throughout the program without the help of auto-complete. The function should be used as a last resort and _["You should always look at alternatives first"](http://stackoverflow.com/a/701813/6486738)_. – Ted Klein Bergman Dec 16 '16 at 01:27
  • @TedKleinBergman like I say in the question, I'm not to good at Python and don't know of any other way to do it this. – George Willcox Dec 16 '16 at 06:49
  • Yes, I understand. My comment was just to inform that if you can use something else then do so. It's a good answer because it answer the question as the asker wants, but if it's going to be used it should come with a couple of warnings. – Ted Klein Bergman Dec 16 '16 at 11:08
0

You could shorten it by creating a list of dictionaries. The list contains the players where player one is first in the list and player four is last. Each player is defined as a dictionary with their class, prey, grand prey and predator.

classes = ['npc1', 'npc2', 'npc3', 'human']  # These are classes
players = []
for i in range(4):
    players.append(
        {
            'class': classes[i],
            'prey': classes[(i + 1) % 4],
            'grand prey': classes[(i + 2) % 4],
            'predator': classes[(i + 3) % 4]
        }
    )

This can be shortened even further into two lines

classes = ['npc1', 'npc2', 'npc3', 'human']  # these are classes
players = [{'class': classes[i], 'prey': classes[(i + 1) % 4], 'grand prey': classes[(i + 2) % 4], 'predator': classes[(i + 3) % 4]} for i in range(4)]

But that might be to push it to far. It's better to have code that stretches over several lines and is readable than vice versa.

Ted Klein Bergman
  • 9,146
  • 4
  • 29
  • 50