3
\$\begingroup\$

Good morning guys!

I've just got done fixing my previous version of this code, and here we are with the "final" version. How would I improve it further?

I wanted to create the board, and the players, but my skillset is severely limited. But I'm trying to improve everyday!

from typing import List, Tuple from random import randint class Robot: def __init__(self, name: str, place : List[int], start: Tuple[int, int] = (0,0), power: int = 100): self._name = name self._place = place self._start = start self._power = power @property def name(self): return self._name @name.setter def name(self, value): if isinstance(value, str): self._name = value else: raise TypeError("must be a string") @property def place(self): return self._place @place.setter def place(self, value): if isinstance(value, list): self._start = value else: raise TypeError("must be a list") @property def start(self): return self._start @start.setter def start(self, value): if isinstance(value, tuple): self._start = value else: raise TypeError("must be a tuple") @property def power(self): return self._power @power.setter def power(self, value): if isinstance(value, int): self._start = value else: raise TypeError("must be a int") @property def check_power(self): if self._power <= 0: raise ValueError("No power") def left(self, value): # self.sprawdz_power() self.power -= value if self.place[0] - value < 0: self.place[0] = self.place[0] - value + 8 else: self.place[0] = self.place[0] - value def up(self, value): # self.sprawdz_power() self.power -= value if self.place[1] + value > 7: self.place[1] = self.place[1] + value - 8 else: self.place[1] = self.place[1] + value if self.place[1] == 5: self.power += 2 def __str__(self): return "{} {} {}".format(self._name, self._place, self._power) def check_position(): to_delete = [] for r_a_nr in range(len(robots)): for r_b_nr in range(r_a_nr + 1, len(robots)): if robots[r_a_nr].place == robots[r_b_nr].place: if robots[r_a_nr].power >= robots[r_b_nr].power: robots[r_a_nr].power = robots[r_a_nr].power + robots[r_b_nr].power to_delete.append(r_b_nr) print(f'Robot {robots[r_b_nr].name} has been slain by {robots[r_a_nr].name}') elif robots[r_a_nr].power < robots[r_b_nr].power: robots[r_b_nr].power = robots[r_b_nr].power + robots[r_a_nr].power to_delete.append(r_a_nr) print(f'Robot {robots[r_a_nr].name} has been slain by {robots[r_b_nr].name}') for i in sorted(list(set(to_delete)), reverse=True): del robots[i] def game(number): for _ in range(number): if len(robots) == 1: print(robots[0].name, "is victorious") break to_delete = [] for r_nr in range(len(robots)): strona_rand = randint(0,1) ruch_value = randint(0,4) if strona_rand == 0: try: robots[r_nr].up(ruch_value) except: to_delete.append(r_nr) elif strona_rand == 1: try: robots[r_nr].left(ruch_value) except: to_delete.append(r_nr) for r_nr in sorted(to_delete, reverse=True): print(f'Robot {robots[r_nr].name} lost all the power') del robots[r_nr] check_position() robots = [ Robot(name = "A", place = [3,4], start = (0,0), power = 100), Robot(name = "B", place = [1,2], start = (0,0), power = 100), Robot(name = "C", place = [1,2], start = (0,0), power = 100), Robot(name = "D", place = [1,2], start = (0,0), power = 100), Robot(name = "E", place = [1,2], start = (0,0), power = 100), ] game(100) 

The logic:

Using the robot class - implement robot battles.

Each player has 5 robots. People move the robots alternately, if the robots meet in one field, one takes part of the energy of the other (or all). When the robot's power runs out, a second robot automatically appears.

or implement a fully random battle

\$\endgroup\$

    1 Answer 1

    4
    \$\begingroup\$

    Your check_position function could use some more improvements. First, I would rename it to something like game_round. Then I would get rid of dealing with indices and directly deal with the robots, and finally I would make the list of robots a parameter of the function:

    from itertools import combinations from random import choice, randint def game_round(robots): for robot in robots: move = choice([robot.up, robot.left]) move(randint(0, 4)) robots = [robot for robot in robots if robot.power > 0] losers = set() for a, b in combinations(robots, 2): if a.place == b.place: loser, winner = sorted([a, b], key=lambda robot: robot.power) winner.power += loser.power losers.add(loser) print(f'Robot {loser.name} has been slain by {winner.name}') return [robot for robot in robots if robot not in losers] 

    I also added the movements into this function now.

    Note that this function, just like yours, allows a robot to be slain by multiple other robots or even slay others and be slain at the same time. This also means that the sum of the powers of all robots is not constant.

    Use it like this:

    def game(robots, num_rounds): for _ in range(num_rounds): if len(robots) == 1: print(f"robot {robots[0].name} was victorious!") break robots = game_round(robots) if __name__ == "__main__": robots = [...] game(robots, 100) 
    \$\endgroup\$
    4
    • \$\begingroup\$Hmmm your function is great and all, but is there any chances to get any other result than victory of robot E? I also want to notice that, when I'm using your code, and using the robots from the list robots, robot A is not doing anything. Also if I have this function game_round, would I give up on function game?\$\endgroup\$CommentedMay 18, 2021 at 11:43
    • \$\begingroup\$@Daro1234451 This function is meant as a replacement of your check_position function. Robot A does not do anything (in round one) because it is not in the same place as any other robot. If it doesn't do anything in the other rounds you probably forgot to assign the output of the function to robots. My function is a "pure function", i.e. it takes some input and returns an output that only depends on the input, without modifying anything in-place, in contrast to your function, which takes no input (just the global variables) and returns no output (but modifies a global variable in-place).\$\endgroup\$
      – Graipher
      CommentedMay 18, 2021 at 11:48
    • \$\begingroup\$Hi i have still one question, would you like to explain it further? I will give u a example: When i was using my function check_positionprogram had different results, for example, if I used check_position in the game function, then after calling: pastebin.com/eUcfP8yw and your function is giving me the same output pastebin.com/QS5T1Y2w all the time, i dont know how to make it play, like go to round 2 or something like that?\$\endgroup\$CommentedMay 24, 2021 at 9:10
    • \$\begingroup\$@Daro1234451 I made the example more complete by also incorporating the movement part. Note that I assign the output of the function back to robots every iteration.\$\endgroup\$
      – Graipher
      CommentedMay 24, 2021 at 9:29

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.