I've also followed all the new additions since I started.
I barely read any of the DM Guide. Of what I have read, it seems like Dan was a pretty witty guy.
(note: I didn't realize how long this would get. I'm not a writer, and I'm definitely not good at predicting if you'll even take the time and effort to go through this. So, there's a tl;dr.)
I don't remember how exactly I figured out language syntax, I think it just came to me naturally after a while.
A lot of programming is basic algebra; variables and functions, as I've come to know it.
You could say d(x)=a(b(c(x))), but d(x) ends up to be one value, of possibly many possible values.
a(x) = x
b(x) = 2*x
c(x) = 3*x
d(x) = a(b(c(x)))
d(4) = a(b(c(4)))
= a(b(3*4)) = a(b(12))
= a(2*12) = a(24)
= 1*24
d(4) = 24
Procedures in DM take input(s) (AKA arguments), and only return one value (AKA the return value).
Operators work exactly the same way, except their inputs are positioned differently.
There are operators that take 1, 2, or 3 inputs, but only return one output.
There's also the >> and << operators, but of those, only the bit-shift operators actually return something.
(Please note that none of this below is magical, undocumented observations. Everything is mentioned in the DM Reference, like short-circuiting and the fact that operators literally have a "return value" like procs do.)
// all of these expressions are true
(-a == -3) (when a == 3)
(!1 == 0)
(3 == 3) == 1
(3 != 3) == 0
(5 && 6) == 6
(4 || 5) == 4
(1 ? 2 : 3) == 2
(0 ? 4 : 5) == 5
What you choose to do with the output is up to you. The important thing is, they don't need an if() to be useful. You can treat the result as any other value, like by storing it in a variable.
A good thing to know about if() statements is, in the end, they're only checking one value (a number, string, object, or null). You can put a ton of operators and procedures (remember, essentially the same) in an if() statement, but in the end, it's just one value.
That's because operators and procedures only return one value.
Combinations of the two don't make a difference, they'll still only return one value.
var hair_r = 255, hair_g = 255, hair_b = 0
if(cake == "lie" && a_if_true("pie") && "Yes" && \
hair_r == 255 && hair_g == 255 && !hair_b)
-> if(1 && "a" && "Yes" && 1 && 1 && 1)
-> if("a" && "Yes" && 1 && 1 && 1)
-> if("Yes" && 1 && 1 && 1)
-> if(1 && 1 && 1)
-> if(1 && 1)
-> if(1)
src << "You poor, cakeless blonde. At least you have pie."
proc/a_if_true(x) return x && "a"
proc/True() return 1
proc/False() return 0
...
var cake = "lie" || a_if_true(!null) && "b" && \
"poo" == "poo" && 1 != 3 && !0 && True() && !False()
Nothing after || matters because cake == "lie".
None of the procs after the || are even called.
This is because of order of operations. (operations -> operator actions)
Playing with order of operations, you can do this:
mob
var locked
Move() return !locked && ..()
..() won't be called if mob.locked is true, the && operator stops at the first false value.
You could even say that only if(1) statements pass if they are read like if(!!(c)), where c is the entire condition.
if("blah" && 2)
-> if(!!("blah" && 2)) // precede condition with !!
-> if(!!(2)) // operate with &&
-> if(!(0)) // operate with !
-> if(1) // operate with !
-> do code
if(null)
-> if(!!null)
-> if(!1)
-> if(0)
-> do code under else
You should understand that if()s aren't as special as you might think. Conditional operators don't require them, similarly to how alert()s don't require a switch() statement to do anything. (alert() is just a proc, nothing more. It returns a value like everything else.)
Variables, however, are everywhere. Everything can be put inside a variable. If you always use call()() instead of calling procs by name, even procs (not built-in) can be put in variables and dynamically called.
var a = "a"
var a_is_a = a == "a"
var a_is_not_a = a != "a"
var pass = "Yay!"
var fail = "Huh?!"
...
if(a_is_a)
world << pass
if(a_is_not_a)
world << fail
var world_makes_sense = a_is_a && !a_is_not_a
if(world_makes_sense)
var double_pass = "Double [pass]"
world << double_pass
proc/a() return "alpha"
proc/b() return "beta"
...
var func_a = /proc/a
var func_b = /proc/b
var a = call(func_a)()
var b = call(func_b)()
world << a
world << b
The above could all be written like this:
if("a" == "a") world << "Yay!"
if("a" != "a") world << "Huh?!"
if("a" == "a" && !("a" != "a")) world << "Double Yay!"
world << "alpha"
world << "beta"
If you consider the last two lines, you might notice that I did a simple replacement.
Realistically, procedures have much more flexibility and can have many different return values.
proc/a_sometimes() return prob(50) ? "a" : "b"
Some procedures don't care about return values, so you'd never use them when considering other things.
proc/say_hello() world << "Hello, world!"
...
if(say_hello()) world << "Huh?"
This has been an over-complication of an extremely simple and fundamental part of most programming anyone will ever encounter:
tl; dr
Variables contain a data; procedures and operators return output data. Wherever you type an operator or procedure, it's replaced by its return value as soon as the code reaches it.
The reason I'm making this post is to make people realize how over-complicated they make some things. I've left out a lot, and if you read anything before the tl;dr, you probably have questions. I'll try to answer them, so long as they're not ridiculous.
Here's a poorly-made fish: </<>
1. They learned to program from looking at some game's code, so the only way they know about switch() and input() is from a menu they saw.
2. They don't have much programming experience and it's fairly logical to make these associations to simplify how you view programming.
3. DM provides useful procs so there's not much you need to add to create basic AI - oview() is the bulk of the work.
When you think about programming like this, it makes you think "what can DM do?" instead of thinking "what can I do?". It puts a low ceiling on what you can accomplish and this is why people make feature requests for things that can easily be accomplished with DM - people just don't realize they can make something if there's not a single DM proc that they associate with the feature.