As a more experienced programmer, instead of asking "how do I do ______?", you should start asking "what's the best way to do ______?". In this post we'll look at different ways to write a simple function to see how certain ways are better than others.
Suppose you have a simple task - you want to find a target for the mob to attack. There are certain conditions we need to take into account. You only target living mobs. You don't target friendly mobs (mobs on your team). And you only target mobs that are more than 4 tiles away. Here's how you might implement this:
for(var/mob/m in oview(10,src))
if(m.alive && m.team != team && get_dist(src, m) > 4)
target = m
break
It's looking kind of messy already but it's still manageable. If you add more to this process it's easy for things to get out of hand. Suppose we create mobs that aren't assigned a team. If a mob isn't on a team it's hostile to everyone. This complicates the check because it's not just enough to check that the mob's not on your team, if both of your team vars are set to NONE they're still a valid target.
for(var/mob/m in oview(10,src))
if(m.alive && (m.team != team || m.team == NONE) && get_dist(src, m) > 4)
target = m
break
Now it's getting messy. You might be thinking "Big deal, I'm not a noob. I'm a good programmer, I can handle a complex conditional statement like that!", but here are some problems you may run into:
1. Don't look at this code for two weeks, then come back to it - it won't be obvious what is happening.
2. If you add more and more conditions to the same if statement you'll eventually lose track of parenthesis and make the code incorrect.
As you learn and become a better programmer you will get better at reading code. But, you'll never get good enough that you read statements like this and understand them instantly. Good programmers don't effortlessly make sense of complex code, they know how to write simple-looking code to do the same thing.
Let's look at one way to make this simpler. You can split up each part of the condition into a separate if statement:
for(var/mob/m in oview(10,src))
if(m.alive)
if(m.team != team)
if(get_dist(src, m) > 4)
target = m
break
Each individual if statement is easy to see, but that much indentation still makes it hard to read. Here's another way to make it more readable:
for(var/mob/m in oview(10,src))
if(!m.alive) continue
if(m.team == team) continue
if(get_dist(src, m) <= 4) continue
target = m
break
The continue statement skips the rest of the current iteration of the for loop and starts the next iteration. We check the opposite of each condition - instead of checking for conditions a valid target must satisfy, we check for conditions that make the target invalid. If any condition makes the mob an invalid target we skip the iteration and look at the next mob.
Another way you can simplify complex conditionals is to store them in local variables. For example:
for(var/mob/m in oview(10,src))
var/too_close = get_dist(src, m) <= 4
var/friendly = m.team == team && m.team != NONE
if(m.alive && !too_close && !friendly)
target = m
break
It's easy to see that the if statement is checking that the mob is alive, not too close, and not friendly. You keep all the complexity in the local variables so the condition is easy to read. There's not a single comment you can put in that code to make it clearer what's happening, the variable names and simplified if statement serve as the documentation.