News for hackers. Stuff that matters.
Re:Solitaire by santoshalper on Thursday February 27, 2025 @11:35AM (#43195918)
What a thoughtful post. I think there is a narrative that localthunk is a "shitty programmer" (which he might very well be), but that by extension, it also means that he just got lucky and bumblefucked his way into massive success - almost as though he didn't know any better.

A post like this dispels that narrative - he clearly put a ton of thought into the design of that game and was incredibly intentional about where he wanted it to go.

Re:Solitaire by npteljes on Thursday February 27, 2025 @12:18PM (#43196356)
He clearly comes across as a conscious game designer as well. And programming doesn't need to be good on today's machines. Many of the indie successes are shit software, like Minecraft, Valheim, Cities Skylines, Project Zomboid, and I'm sure there's many others. Great product design and PR are infinitely more important than software quality.
Re:Solitaire by mikepurvis on Thursday February 27, 2025 @11:41AM (#43195985)
In what quarters is that narrative? Surely one only has to play Balatro for an hour or two to understand the incredible game design effort that underpins it all, which is brought so vibrantly to life by the music, art, animations, and all the rest of it.

I can't imagine someone appreciating all this and still managing to poo poo it over a few bugs or maybe some quibbles about it having been built in Lua.

Re:Solitaire by dilDDoS on Thursday February 27, 2025 @12:17PM (#43196349)
People that mention this are usually referring to this chunk of the source code: https://www.reddit.com/r/programminghorror/s/KmEWRILR1q

My assumption is that a lot of the people that look at small chunks of code and judge someone’s programming ability are people who have only worked in corporate environments and have never had to build a large project on their own, and don’t have any understanding of the effort it takes to make a game like Balatro by yourself. Maybe that’s an unfair judgment. But so is calling LocalThunk a “shitty programmer” over some questionable if-else logic.

Re:Solitaire by slongfield on Thursday February 27, 2025 @01:23PM (#43196947)
People love to dunk on hacky looking gamedev code. Some of it is pretty ugly, e.g, VVVVVV's famous gigantic switch statement, but if it works and makes a fun game, that's the actually important part.
Re:Solitaire by IsTom on Thursday February 27, 2025 @01:10PM (#43196839)
It's verbose and could be simplified, but also looks like something you write once and never look at again. If it works it makes no sense to spend any more time on it.
Re:Solitaire by AnIrishDuck on Thursday February 27, 2025 @02:15PM (#43197466)
Yeah, working on a game myself and ... sometimes you just gotta do stuff like that.

Working on a game solo requires juggling several wildly different disciplines at the same time. Sometimes you're in "game designer" mode, you need to fix a bug or add a feature, and you bonk in the caveman thing that obviously works.

Solo gamedev is basically the "startups should accumulate technical debt" meme on steroids. As long as you can understand the code, nobody cares about how it looks. Only how the game plays.

Re:Solitaire by ARandumGuy on Thursday February 27, 2025 @12:08PM (#43196255)
Even if the underlying code is "bad", who cares? There are far more important skills in indie game development then programming ability. I'd much rather play an interesting, well-designed game with a few bugs and messy code over a well-programmed but boring game.
Re:Solitaire by mattnewton on Thursday February 27, 2025 @11:46AM (#43196038)
I have never heard that assertion, I don’t know how anyone can play Balatro and not feel that it is a deeply intentional creation. I think localthunk would be the first to tell you they got lucky with how it found an audience outside of themselves, but everything in the game oozes polish and intention.
Re:Solitaire by datadrivenangel on Thursday February 27, 2025 @11:49AM (#43196067)
The assertions are more around code quality. Game design is wonderful.

Apparently there are places where the code is like a thousand lines of if card_name then effect.

Re:Solitaire by meheleventyone on Thursday February 27, 2025 @11:59AM (#43196167)
For a project with lots of variation being maintained by a single person that’s totally fine.
Re:Solitaire by Trasmatta on Thursday February 27, 2025 @12:01PM (#43196186)
Yep, there are days I yearn for just having a super long set of if statements, vs the over-engineered messes that I deal with on a daily basis.

So many codebases end up impenetrable in the pursuit of fancy design patterns...

Re:Solitaire by npteljes on Thursday February 27, 2025 @12:26PM (#43196442)
I think that too fancy code is just as bad as the original if-else spaghetti, but then even worse, because the patterns are abstract now as well.
Re:Solitaire by npteljes on Thursday February 27, 2025 @12:25PM (#43196422)
Bad code can have a really high cognitive load to maintain. Just to illustrate what bad means, take a look at this:

https://www.reddit.com/r/programminghorror/comments/1cb6rca/...

I can see that having even bits of modification impacts lots of lines, where if written just a bit more saner, it could impact just a few.

Of course everyone is absolutely free to do the things however they want on their project. It's just that bad code, and bad choices bite back sometimes really badly. Project Zomboid is built in LUA for example, and it shows, it's a horrorshow not just to play, but to develop it as well. Their programmers spend a lot of time with just refactoring things. Besides functionality, maintainability should be a huge focus in my experience, so that the devs don't hate life if they have to touch the code again.

Re:Solitaire by meheleventyone on Thursday February 27, 2025 @12:37PM (#43196549)
The example you post is out of context and maybe a bit overly verbose but again it’s one guy maintaining it and is perfectly readable. Does anyone really struggle to understand that?

I’m back working on a twenty plus year old codebase (and game) that’s ~3 millions loc and would kill for something simple like that rather than some of the overabstracted crimes lurking within.

Re:Solitaire by AnIrishDuck on Thursday February 27, 2025 @02:19PM (#43197501)
Yeah, without context criticism of this code is silly.

What if this wasn't always how cards worked? What if the mapping was (at one point in development) not straightforward? Or localthunk had some ideas and wanted to leave the door open to a more complex mapping scheme?

Re:Solitaire by npteljes on Friday February 28, 2025 @03:14AM (#43203069)
Either silly, or 20 years in the business.
Re:Solitaire by npteljes on Friday February 28, 2025 @03:17AM (#43203090)
The problem is not with understanding, but with maintainability. If you need, for any reason, to touch that code again, instead of a few changes, you have to be consistently doing a lot of changes. This has a higher chance of manual errors. And it has nothing to do with other bad code, like the one that you encounter. Both can be bad code, and what you inherited sounds worse. I hate it when the badness is compounded with complexity. It feels pretentious to me.
Re:Solitaire by meheleventyone on Friday February 28, 2025 @04:41AM (#43203670)
That code is a few lines maintaining a mapping though, changing it is not going to be hard and all the mappings are captured explicitly which makes it even more straightforward versus shaving off lines of code by making some of them implicit (e.g. by seeing a pattern in the mapping and using an if statement to capture them all). I'd really love to know what you think it should be to be more maintainable!
Re:Solitaire by npteljes on Friday February 28, 2025 @05:30AM (#43204028)
Something like this would pass a code review, while the original would not:

  function createObject(value, id, nominal)
      return {
          value = value,
          id = id,
          nominal = nominal
      }
  end
  
  local objects = {
      createObject(100, 1, "nominal1"),
      createObject(200, 2, "nominal2"),
      createObject(300, 3, "nominal3"),
      createObject(400, 4, "nominal4")
  }
Still far from ideal, but I'm not that familiar with LUA either. And I do acknowledge that bad code can work, and heck, even I write them sometimes. My original point is that it has downsides and risks, and so I don't consider it fine. I have dreaded to touch such code (mine and others) many times, and made mistakes because of past laziness like that, many times.
Re:Solitaire by meheleventyone on Saturday March 01, 2025 @06:42AM (#43218335)
This is not equivalent though so you fail my code review. :D

For starters its clear the code in the example expects self.base.value to already hold a value. So constructing an object blind isn't necessarily what's happening here, it's possible an existing object is even being decorated with extra fields. So your suggestion isn't preserving the semantics.

Secondly for the face cards there is an additional field being set which is not happening in your case.

That's what I mean when I said earlier that we can't just look at a piece of code contextless and say it's bad. Your refactor is definitely neater if we're initializing homogenous objects but that's an incorrect assumption on your part. It also comes with trade-offs for example it's not obvious anymore what any of the values relate to without going to the function constructing the object. Not the biggest thing in the world but if this is the only place in the codebase doing this then I'd argue that it probably isn't worth it.

Re:Solitaire by bongothrowaway on Thursday February 27, 2025 @12:40PM (#43196572)
Undertale's code base is apparently no better. For games I don't think code quality is nearly as paramount; there's not a whole lot of maintenance going on there, though this doesn't apply to live service games.