Im working on a game that, if done well, should appeal to people who like automation games, like Factorio, Industrialist, or Mini Megafactory. In my game, you will control an army of drones in a real-time-strategy style 2D world. The catch is that you only directly control your leader, everything else is controlled by programs you write and download into your units.
This is a huge initial learning investment for players, which I’m trying to control by making the language as simple and gamified as possible. Once that’s overcome, there is massive opportunity for emergent strategies, something that I believe automation games need to thrive. A little bit of research into my target audience could go a long way here.
Could someone with business development or social media management sense give me an idea of how to do this kind of research?
TikTok, Youtube and Reddit are probably your best bets, you already stated some of the names of the games within the genre of the game you’re making, so look at stuff like gameplay and those platforms have pretty good recommendation systems when it comes to finding videos that are similar to the one you’re watching so that could be of use aswell
Could you tell us more about the game? @azqjanna
Yes, here is my long-form summary.
You and your opponents both start with one unit, your only “autonomous” drone whose programs you can directly edit. You use this starting unit to collect resources and manufacture components, including additional drones. Each drone starts out as a blank slate with no abilities. You specialize each drone by attaching extra components such as sensors, weapons, and methods of movement.
Strategy in this game revolves around how cleverly you design your swarm. Do you want a small number of units each with many abilities and lots of flexibility? Or do you want a low-cost army of specialized units? For example, not every drone needs to be able to detect its surroundings, it could instead receive position commands from a designated leader. Having very cost-optimized military units could make a huge difference in combat.
As your forces expand further out, you need to deal with complexity in communication. While you can transmit commands directly from your leader to nearby drones, sending communication long distance requires planning, and takes significantly more time to send large transmissions. Keep in mind that if your opponent figures out how exactly how your programs work, they may find holes in your strategy. Don’t let your drones or their transmissions fall into enemy hands!
Here is a concept sheet I made for how components could work:
Im thinking of potentially finding other automation games with programming aspects and seeing if people have said anything interesting about them. I know Mindustry has such a feature and I for sure didn’t like it, will have to revisit.
My two favorite games, Oxygen Not Included (which is more of a colony sim, but still has technical aspects) and Factorio, start off fairly slow. In factorio, you have very simple mining drills, and furnaces, no conveyors even, which makes it much more approachable to learn for new players (albeit I got quite bored of the early game). An example of how the devs tweaked the progression of the game was the introduction of the basic oil process for oil refining, before then, you were introduced strait into all the different types of oil and the need to do cracking
What have you opted for, for your language? I know a lot of games use simple bitwise wires and logic gates, and while simple, it isn’t very powerful. I particularly like how factorio does its logic, but a lot of players don’t touch it, due to it being more complex (or it just not being what those players like doing)
Its a very simple language that is aesthetically similar to Lisp. I have designed it to be easy to type, so it has no parentheses or symbols. It’s similar to what you might find in an educational programming game. It also lends itself nicely to a drag-and-drop editor, which might be more friendly to some players and make playing on mobile more of a possibility.
Like a lisp without parenthesis?
Take a look at Haskell for inspiration on that. Haskell is a strongly typed Lisp with no parenthesis.
squareAndSum :: [Int] -> Int
squareAndSum = sum . map (^2)
P.S.:
I, and I’m sure many others, find PascalCase odd for keywords and functions.
I’d recommend keeping PascalCase to types,
either camelCase or snake_case for functions,
and lowercase for keywords
Its optimized for typing and only builtin functions are uppercase, so they autocomplete in one or two letters.
I do want a type system eventually though, mostly so I can do overloading for things that make gameplay sense. E.g. if you call SetNav with a Position instead of two separate X and Y numbers, it will still work, and if you call any type with a Sequence of that type instead, it takes the leftmost item so you don’t need to explicitly index it.
Yeah, that makes sense. For typing user-defined functions, you should use something akin to Haskell’s since it fits your syntax already
What do you mean by this? Like, typing on a keyboard or a type system? If it’s the latter, what kind of type system? Is it dynamic? Is it strong? Is it static? Is it gradual? etc
That makes sense, but why are keywords also capitalized? I feel like you could just give them a higher priority in your autocomplete (same with prelude functions)
My terminology is a little confusing right now so let me start from the top.
I have absorbed the concept of keywords into being functions as well. The only difference between “SetNav” and “Task”, which are both functions, is that “Task” needs to talk to the parser, while what SetNav does at runtime the parser doesn’t care about. Functions are defined as soon as the Task function (and following statements) are parsed, as opposed to executed, the latter being the case in Lua. A statment is just the outermost function call on a line, and it must be terminated by the end of the line. I have found this makes generating good errors pretty easy, which is important for player feedback.
By typing I meant user input. For this game to be fun during tense moments I need to minimize frustration when coding. I have chosen to avoid all forms of matched character like ( )
or [ ]
. I am also trying to avoid symbols as much as possible. Even though I am internationally recognized as the #1 Python hater, I have chosen to use block indentation because it helps avoid matched tokens (do end
style) or confusing statement termination rules.
While it hasn’t been borne out yet, I hope all these things enable lots of autocomplete and autocorrect type assistance. For example, if the user typos SetNavx y
, the parser knows that the first token on a line needs to be a defined function, of which SetNavx
isn’t, but its prefix SetNav
is. What’s left is a defined variable, which matches the required next token to SetNav, so it can confidently autocorrect this case.
Finally, because the language is pre-fix, all this assistance can be down as soon as an expression is closed. In an in-fix language, any remaining open-parentheses effectively puts this checking on pause, which means the player is not getting feedback until they’ve written a REALLY long expression and the errors may be real bad.
Thanks for the clarification. I understood where you’re coming from for most of it, but:
Yes, I know that’s how Lisps work. I used the word “keywords” to be more specific as to what prelude functions I was talking about.
Figured, I just wanted to make sure I wasn’t misunderstanding.
How do you represent lists/arrays, then? What if I need to input a list into a function? You should still allow for them to be used like in Haskell. one (two (three four))
I have a plan for arrays, which I’m calling sequences. You can create them with one of Set’s overloads, which is variadic:
Set x 1 2 3
→ (1, 2, 3)
I could add a version which is an expression instead of an assignment:
Seq 1 2 3
When I add types, Sequences will be required to contain variants of the same type. I will try to avoid the need to break this rule, because I don’t want the player to have to think about types too often.
You can include this expression in a line that requires a sequence as input. Since it’s variadic, there’s an explicit token to terminate variadic argument lists:
SomeFunction Seq 1 2 3; Seq 4 5 6;
The last ;
is optional becuse the end of a line inserts those until the first function is closed. There are some cases that I don’t like with this system. I’ll give an example when I remember what those are.
An example of a way you could use this in-game: Sensor calls give you a Sequence of detections sorted by range. If you only care about the closest detection of a type, such as for collecting resources, you can just filter it by Resource then pass it directly to SetNav. SetNav will first take the left-most (closest) Detection, then realize that it’s not the right type, but only contains one child that matches the type it wants (a Position), and automatically index that. This is highly janky for a general-purpose language, but exactly as terse as it should be for the game.
SetNav Filter Resource; Optics Scan
How the parser will treat it, in-fix style:
SetNav(Filter(Resource, Optics.Scan())[0].Position)
That’s postfix, not infix. a + b
is infix.
Personally, I think your language is pretty unreadable, and for your goal I feel like you want the opposite.
I think you should really look into other languages. Specifically for $
and |>
. Since they’re infix, you probably wouldn’t use $
or |>
directly, but something similar would greatly improve the readability of your language.
$
is the function application operator. It lets you avoid parenthesis (hey! that’s what you’re trying to do!)
print $ length [1,2,3,4] -- prints "4"
-- that's equivalent to
print (length [1,2,3,4])
If you want to know how it’s defined in Haskell,
($) :: (a -> b) -> a -> b
f $ x = f x
The pipeline operator |>
in languages like F# and OCaml is very similar. It pipes the left-hand value into the first parameter of the right-hand function.
"Hello!" |> printfn // prints "Hello!"