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.
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.
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.
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.
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.
Apparently there are places where the code is like a thousand lines of if card_name then effect.
So many codebases end up impenetrable in the pursuit of fancy design patterns...
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.
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.
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.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.
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?