Drawing a planetary system in Pygame
Your code is very procedural. Do this, do that, do another thing. There's nothing inherently wrong with this, but the only OOP in the code you've shown is that of pygame itself. There's a little bit hinted at by the game and player objects, and perhaps the logbook dictionary, which appears to hold some other kind of object. But the way you interact with all of these things is all very procedural.

So, how can you better leverage OOP?

The biggest change I would suggest is to avoid big long series of attribute accesses. Things like self.game.player.logbook[p.name].is_explored represent at best a misuse of OOP. What does this code try to do? It tries to answer if a player has explored a planet. How does it do so? By asking if the planet's name appears in the player's logbook, and if the resulting object has the right attribute set.

So how should this question look in code? It should mention as few of the other objects as possible. Ideally it would look like one of the following lines; choose one and stick with it:

player.has_explored(planet)
planet in player.explored_planets
planet.explored_by(player)
player in planet.explorers
game.planet_explored_by(planet, player)


Now, you might have to get your local planet or player variable from some other collection, but you don't want to have to know it's tracked in the game's player's logbook, indexed by planet's name, and stored in an an attribute called is_explored. Only the tiny function that answers that question should have to know any of that extra stuff, and then if you ever move the information, only that one function has to be updated.

Once you've chosen the new way to ask if a planet has been discovered and explored, update your code to use it. Then look for repetition, or otherwise unnecessary checks. They're distracting to read, and possibly slow your code down. For example, you currently create a list planets_to_blit that includes only planets that have been discovered. Then you iterate over this list to draw halos, but first check again whether the planet was discovered.

If you break the function into multiple pieces (say one helper that retrieves the planets, and another that draws halos), it's hard to know whether the check was performed before calling the second helper. However, instead of repeating the check as an if, consider adding it as an assert in the halo drawing helper. This documents to the reader of the code that the helper should only receive planets that have been discovered, and the resulting exception helps you to find callers that didn't make sure.

There are other small or cosmetic changes I would suggest:


Don't be explicit about comparing against True and False; prefer if x: ... or if not x: ...
Leverage some of the self-documenting features of python: in particular consider using docstrings instead of a comment before a function (on the flip side, consider avoiding the docstring-like string literals anywhere else in a function; use comments or extra functions if you need these)
Use whitespace a bit more liberally: tastes differ, but I like to group related lines into blocks and use empty lines before and after, and I like to have spaces after the # character
Be careful with spelling: in specific, hoover is a vacuum cleaner; hover is the term you're looking for


Now I want to circle back to your question about side effects. Once you've split up your code into smaller helper methods, a good split will often have some of the following properties for each method:


The method only relies on knowledge about one area - this is the first thing I talked about
The method will either only retrieve and filter data, or it will only modify data - for example, one method could retrieve all discovered planets, and another could draw lines for the planets that are passed to it
The method doesn't assume things that aren't in its name - for example a get_planets method wouldn't filter the results to just the discovered planets


If we look at your original code, the view_solarsys function violates all of these to some degree. It would be a lot nicer if it looked more like this:

def draw_solarsys(self):
    """Draw the discovered planets, and links between them."""

    discovered_planets = self.get_discovered_planets()
    for planet in discovered_planets:
        self.draw_SFO_for_planet(planet)

    mouse_pos = pygame.mouse.get_pos()

    for planet in discovered_planets:
        self.draw_planet_with_aura(planet)

        if planet.rect.collidepoint(mouse_pos):
            self.draw_planet_info(planet)
            if self.game.map_active:
                self.handle_clicks(planet)


Is that perfect? Of course not. But I think it helps.