4
\$\begingroup\$

I am making a river crossing puzzle app using Pygame. Did I implement the conditions optimally?

The Person class arguments for the conditions as to when or not a person will cross a river are these:

  • hate=[]: If any of the names in the list are the names of any people in boat.aboard, don't cross.

  • like=[]: If none of the names in the list are the names of any people in boat.aboard, don't cross.

  • alone=True: If there is anyone in boat.aboard besides himself in the boat, don't cross.

  • alone=False: If there is no one in boat.aboard besides himself in the boat, don't cross.

Here is where I implemented the conditions:

    def go(self):
        hated = [name for person in self.aboard for name in person.hate]
        liked = [name for person in self.aboard for name in person.like]
        no = False
        if any(person.alone == True for person in self.aboard) and len(self.aboard) > 1:
            no = True
        elif any(person.alone == False for person in self.aboard) and len(self.aboard) == 1:
            no = True
        elif any(person.name == name for person in self.aboard for name in hated):
            no = True
        elif liked:
            if any(person.name == name for person in self.aboard for name in liked):
                no = False
            else:
                no = True
        else:
            no = False
        if not no:
            if self.side == 'UP':
                self.y += 300
                self.side = 'DOWN'
            else:
                self.y -= 300
                self.side = 'UP'
            self.obj.y = self.y

I want to know if I implemented the conditions above ^ optimally, or even correctly.

Here is when I run the entire code, and the conditions seem fine:

enter image description here

And here is my entire code:

import pygame
import random

pygame.init()
wn = pygame.display.set_mode((600, 600))
font = pygame.font.SysFont('Arial', 25)
people = []

class Person():
    def __init__(self, name, x, y, color, side='UP', w=20, h=20, hate=[], like=[], alone=None):
        self.name = name
        self.color = color
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.alone = alone
        self.hate = hate
        self.like = like
        self.side = side
        self.obj = pygame.Rect(x, y, w, h)
        people.append(self)
        conditions = []
        if alone == False:
            conditions.append("won't go alone")
        elif alone == True:
            conditions.append("will only go alone")
        if len(hate) > 1:
            conditions.append(f"won't go with any of: {', '.join(hate)}")
        elif len(hate) == 1:
            conditions.append(f"won't go with {hate[0]}")
        if len(like) > 1:
            conditions.append(f"will only go if any of: {', '.join(like)} are going")
        elif len(like) == 1:
            conditions.append(f"will only go if {like[0]} is going")
        self.conditions = conditions

    def draw(self):
        self.obj = pygame.Rect(self.x, self.y, self.w, self.h)
        pygame.draw.rect(wn, self.color, self.obj)

    def get_on_boat(self, boat):
        self.x = random.randint(boat.x, boat.x+boat.w-self.w)
        self.y = random.randint(boat.y, boat.y+boat.h-self.h)
        self.side = boat.side

    def write_conditions(self, x, y):
        text = font.render(f"{self.name} {'; '.join(self.conditions)}", True, (0, 0, 0))
        wn.blit(text, (x, y))

    def get_off_boat(self, boat):
        self.x += random.randint(50, 200)

    def on_boat(self, boat):
        return boat.x+boat.w-self.w >= self.x >= boat.x and boat.y+boat.h-self.h >= self.y >= boat.y

class Boat():
    def __init__(self, room, x=280, y=200, color=(140, 140, 140), w=40, h=60, side='UP'):
        self.room = room
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.trips = 0
        self.color = color
        self.obj = pygame.Rect(x, y, w, h)
        self.side = side
        self.aboard = []
        
    def go(self):
        hated = [name for person in boat.aboard for name in person.hate]
        liked = [name for person in boat.aboard for name in person.like]
        no = False
        if any(person.alone == True for person in self.aboard) and len(self.aboard) > 1:
            no = True
        elif any(person.alone == False for person in self.aboard) and len(self.aboard) == 1:
            no = True
        elif any(person.name == name for person in self.aboard for name in hated):
            no = True
        elif liked:
            if any(person.name == name for person in self.aboard for name in liked):
                no = False
            else:
                no = True
        else:
            no = False
        if not no:
            if self.side == 'UP':
                self.y += 300
                self.side = 'DOWN'
            else:
                self.y -= 300
                self.side = 'UP'
            self.obj.y = self.y

    def draw(self):
        pygame.draw.rect(wn, self.color, self.obj)


boat = Boat(2)
Yel = Person('Yel', boat.x+100, boat.y, (255, 255, 0), hate=['Red']) # yellow
Red = Person('Red', boat.x-100, boat.y, (255, 0, 0), alone=True) # red
Pin = Person('Pin', boat.x+200, boat.y, (255, 0, 255), like=['Yel']) # pink
Blu = Person('Blu', boat.x+250, boat.y, (0, 0, 255), like=['Yel'], hate=['Gre']) # blue
Gre = Person('Gre', boat.x+280, boat.y, (0, 255, 0)) # green

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            for person in people:
                if person.obj.collidepoint(pygame.mouse.get_pos()):
                    if person in boat.aboard:
                        person.get_off_boat(boat)
                        boat.aboard.remove(person)
                        boat.room += 1
                    else:
                        if boat.room and person.side == boat.side:
                            person.get_on_boat(boat)
                            boat.aboard.append(person)
                            boat.room -= 1

            if not any(person.obj.collidepoint(pygame.mouse.get_pos()) for person in people):
                if boat.obj.collidepoint(pygame.mouse.get_pos()):
                    if boat.aboard and boat.room >= 0:
                        boat.go()
                        for person in boat.aboard:
                            person.get_on_boat(boat)
                        boat.trips += 1
                    
    wn.fill((255, 255, 255))
    pygame.draw.rect(wn, (100, 200, 255), (0, 290, 600, 180))
    boat.draw()
    for i, person in enumerate(people):
        person.draw()
        person.write_conditions(0, i*25)
    

    pygame.display.update()

Also, I want some suggestions to clean up my messy code.

\$\endgroup\$
1
  • \$\begingroup\$ In the Person class, I would. move those if/elif statements out into either a separate method (maybe an @staticmethod), or to a standalone function (if you don't like static methods). This might also be a good case for using dataclasses. \$\endgroup\$
    – Z4-tier
    Nov 4, 2020 at 5:12

0

Your Answer

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

Browse other questions tagged or ask your own question.