ID:120895
 
Be sure to check out:
Programming Tips #1 - If Statements
Programming Tips #2 - Making Progress
Programming Tips #3 - Design
Programming Tips #4 - Datums
Programming Tips #5 - Organization
Programming Tips #6 - Procs & Organizing Code
Programming Tips #7 - Comments and Whitespace


When you first start programming, the problem you're trying to solve is "how do I write code that'll do ______?". Initially you're happy just to get something working, who cares what the code looks like. But when you try to develop a complete game this indifference can become a problem. As your code gets messier and messier, the project becomes harder to work on - you're more likely to write code that has bugs and they become harder to track down and fix. Eventually it'll get to the point where you're wasting a lot of time, don't feel productive, and are more likely to stop working on the project.

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 how using if statements and loops certain ways can improve the readability of your code.


There are many ways to write a proc that does a certain task. This means that there are many uses for the same basic DM language structures - variables, procs, and loops can all be used for many different things. This creates a problem. When you're reading code you have to figure out how each part is being used.

We make this easier by only using certain tools for certain tasks. For example, for loops and while loops are interchangeable - any for loop can be written as a while loop and any while loop can be written as a for loop. Even though they're essentially the same, we use them for different tasks to make the code easier to understand.

This lets you make assumptions when you're reading code so you can easily look at a for loop or if statement and understand what's going on.

Loops


A for loop is used to iterate over a bounded set:

for(var/i = 1 to 7)

for(var/mob/m in view())

for(var/area/a in world)

The for loop itself clearly defines the set of values you're looping through. We could use a while loop or recursion to do the same thing but the set of values wouldn't be as clear:

// first way:
for(var/i = 1 to 7)
world << i

// second way:
var/i = i
while(i <= 7)
world << i
i += 1

// third way:
proc
do_something(i)
if(i <= 7)
world << i
do_something(i + 1)

do_something(1)

These all do the same thing but the first method is the most clear.

A while loop is used to loop while a condition is true:

var/name = ""
while(!name)
name = input("Please enter your name:")

The loop continues as long as no name has been entered. In these types of loops we don't care about a set of values or how many times the loop runs, we care about the condition that keeps the loop going. A while loop makes the condition clear, so we wouldn't use a for loop in this case.


This is why the goto statement isn't used. You can use the goto statement to create a loop, but the kinds of loops you create will almost always be a type that's more clearly represented by using a for or while loop.

If Statements


An if statement checks a single condition. This isn't a problem I often see, but sometimes people use loops instead of if statements.

// some people might do this:
for(var/mob/m in oview(5,src))
attack(m)
break

// instead of this:
var/mob/m = locate(/mob) in oview(5, src)
if(m)
attack(m)

Using a loop in this case is bad because you're not really using a loop. You're just using the loop as an if statement - the loop's body will execute either zero times or one time, just like the body of an if statement. The reason it's bad to use a loop in this case is because whoever reads the code will see a loop and expect certain things to be true. Because you're not really using it as a loop, none of those assumptions will be true and the code will take more time to understand.

Another thing to keep in mind about if statements is whether you use the if statements body to handle the nominal case and use the else clause to handle the exception or the other way around. For example:

// first way:
if(valid)
// do something
else
// handle the error

// second way:
if(!valid)
// handle the error
else
// do something

Both methods do the same thing. The first way is better because people expect the if statement to check for the desired condition and its body will handle the nominal case. It's expected that the else clause handles the unexpected or undesired case. Both examples do the same thing but the first way makes more sense. You can avoid this by not using else clauses:

var/result = do_something()

if(isnull(result))
// handle this kind of error
return

if(result < 10)
// handle this other kind of error
return

// handle the case where the result is valid

The if statements are used to check for bad conditions. If all checks pass, the result is known to be good and the processing occurs.

My first programming tips article covers some other concerns about if statements - particularly how to write the conditions in clearer ways.


This is a simple topic but it's one of the first things that people stumble on when transitioning from "newbie" to "intermediate". A newbie is just happy to write code that works. An intermediate programmer isn't just concerned with getting code working, they're concerned with how it works and how it's organized. If you have the mindset "the code works, who cares what it looks like?" you're going to be stuck in the newbie stage. To work on larger, more complex games and be able to see them through to completion you'll have to be concerned with how your code is organized.
Thanks man!
I'm not sure what you're asking.
LightningNinja91 wrote:
Some people believe using goto is wrong, yet others believed that it's "okay" to use it.

You'll find that a for loop or while loop almost always make more sense than goto. It's not that it's right or wrong, it's just never the clearest way to write code.
I don't even know what a loop is. But it's still beauitful, Forum.


And tell me, does the following make sense: "Could you work on an library concerning automated turf/tile placement on a map?"
You should also mention the 'step' keyword.

for(var/i = 1 to 100 step 5)
Nadrew wrote:
You should also mention the 'step' keyword.

> for(var/i = 1 to 100 step 5)
>

Geez, I've never used "for" like this, I use:

for(var/i=0, i<7, i++)
You should never use for in an only way.
Your code must have flexibility, meaning you could of use for() like you do in some cases. But it's also good to use it in another syntax like Nadrew said.

If you use always the same programming method, the same ways, you will be stuck and make 0% progression.
Anyways am not telling you how to do your programming, just try'ng to clarify terms.
Megablaze wrote:
Nadrew wrote:
> > for(var/i = 1 to 100 step 5)
> >

Geez, I've never used "for" like this, I use:

> for(var/i=0, i<7, i++)
>

Those do two completely different things..?

Nadrew's example will increase at increments of 5: 1, 6, 11, 16, etc. until it reaches 96 (?Or 100? 101? Nadrew or FA can clarify, too late at night to bust open DM and check). Your example (Darwin) will simply count to 7 at increments of 1: 0, 1, 2, 3, etc.
F0lak wrote:
Megablaze wrote:
Nadrew wrote:
> > > for(var/i = 1 to 100 step 5)
> > >

Geez, I've never used "for" like this, I use:

> > for(var/i=0, i<7, i++)
> >

Those do two completely different things..?

Nadrew's example will increase at increments of 5: 1, 6, 11, 16, etc. until it reaches 96 (?Or 100? 101? Nadrew or FA can clarify, too late at night to bust open DM and check). Your example (Darwin) will simply count to 7 at increments of 1: 0, 1, 2, 3, etc.

Yeah... obviously... I could've wrote "for(var/i=0, i<100, i+=5)" instead, I just meant the way to write "for" loops, apparently you didn't get that... I was also using the example in the post, rather than the comment, the comment simply included "step" which was more complete.

Edit:
"for(var/i=1, i<=100, i+=5)" <- I meant that.
The article assumes you know how to write a for loop. It's more about why or when you'd use them. The reference covers how to write them, so I wouldn't mention that you can use the other format or that you can use "step", but I'd mention why you should or shouldn't use those formats.

for(var/i=0, i<7, i++)

This way tend to be less readable because you have to be mindful of the condition. You have to look and see if it's < or <= to see what the range of values is. It's more readable to use the other format:

for(var/i = 0 to 7)

You can't make a mistake about the range of values there.

Using "step" can also be confusing. If possible, the only time you should use it is to say "step -1" to make the loop go backwards. Using a number larger than 1 can be confusing because it's not always clear what the last number in the range will be.

for(var/i = 1 to 100 step 5)

The last value in this set is 96, but that's not immediately clear from looking at the code. Needing to skip values isn't common, but if you wanted to output the first 20 multiples of 5 you could do this:

for(var/i = 1 to 20)
world << i * 5

Instead of trying to mess around with step to get it right, you write a loop that clearly has 20 iterations and outputs multiples of 5.
Masterdarwin88 wrote:
And tell me, does the following make sense: "Could you work on an library concerning automated turf/tile placement on a map?"

I'm not sure what you mean. Are you talking about generating maps automatically? Or do you mean that tiles will autojoin so you can place a single "road" turf and it'll set its own icon state to make it look correct.
Forum_account wrote:
Or do you mean that tiles will autojoin so you can place a single "road" turf and it'll set its own icon state to make it look correct.

I think an article concerning bitflags and bitwise operators could be useful. A lot of people don't really know what they are or how to use them.