Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 2 [3]

Author Topic: Coding for absolute beginners?  (Read 5896 times)

i2amroy

  • Bay Watcher
  • Cats, ruling the world one dwarf at a time
    • View Profile
Re: Coding for absolute beginners?
« Reply #30 on: October 25, 2016, 04:58:41 pm »

Pretty sure in C and C++ you need to actually write "break;" instead of just ";" after each case (unless you are specifically trying to fall-through, that is).

BTW we do have a coding thread over in general discussion for anyone who wants some help/advice that gets answered a fair bit more regularly than this does.
Logged
Quote from: PTTG
It would be brutally difficult and probably won't work. In other words, it's absolutely dwarven!
Cataclysm: Dark Days Ahead - A fun zombie survival rougelike that I'm dev-ing for.

Thief^

  • Bay Watcher
  • Official crazy person
    • View Profile
Re: Coding for absolute beginners?
« Reply #31 on: October 26, 2016, 04:29:41 am »

And if you're trying to fall-through, you don't need the ";" anyway.
Logged
Dwarven blood types are not A, B, AB, O but Ale, Wine, Beer, Rum, Whisky and so forth.
It's not an embark so much as seven dwarves having a simultaneous strange mood and going off to build an artifact fortress that menaces with spikes of awesome and hanging rings of death.

McTraveller

  • Bay Watcher
  • This text isn't very personal.
    • View Profile
Re: Coding for absolute beginners?
« Reply #32 on: October 26, 2016, 11:58:21 am »

Is this the proper thread to cry tears into?

I have a chunk of c++ here.  The former


Works

this:

Throws errors about zom not being defined.  I dont know.  If I add a mtype_id before zom they read (and then the line add_spawn(zom, 1, zx, zy); fails to read 'zom'), but I shouldnt have to?  zom is simply shorthand for a specific group of monsters.  I am sure Ive otherwise defined the specific critters.


I saw lots of posts about using a switch/case below, but didn't see any that explained why you got the errors.  At the risk of giving you an answer you already got:

In C-like languages, you have to declare a variable before you can use it. There is also a concept of 'scope', which is basically a section of your code that knows about certain information.

In your second code, you had something that looked like

Code: [Select]
} else {
    mtype_id zom = mon_zombie;
} if (one_in(50)) {
    zom = mon_zombie_child_scorched;

This code declares a variable called 'zom', but notice how it's inside a {} group?  That means that only other code inside that {} knows about 'zom'.  So when you tried zom = mon_zombie_child_scorched in a different {}, that second area doesn't know what 'zom' is.

Each {} defines a 'scope' in C-like languages. There are actually some complex rules about scope, but generally you can access things defined inside a scope or at a higher scope.

So to fix your situation, you want to change the code into something like
Code: [Select]
mytype_id zom;
if() {
:
} else {
   zom = mon_zombie;
}

if ( one_in(50) ) {
  zom = mon_zombie_child_scorched;
}

Note also I moved that last 'if' to a separate line - putting it next to the closing bracket for the else can be confusing.
Logged

McTraveller

  • Bay Watcher
  • This text isn't very personal.
    • View Profile
Re: Coding for absolute beginners?
« Reply #33 on: October 26, 2016, 11:59:34 am »


I find it is easier to work with, and does not confuse compilers as much.


Please let me know which compiler(s) get confused by if-else constructs, so I can avoid them like the plague!  :o
Logged

Reelya

  • Bay Watcher
    • View Profile
Re: Coding for absolute beginners?
« Reply #34 on: October 26, 2016, 03:47:13 pm »

I think it's more that they're confusing for the programmer, hence the compiler thinks you're trying to do something different to what you actually want it to do. The compiler works by pretty strict logic however.

Another thing to keep in mind when doing if-else is that if is faster than else. That includes times you didn't actually write the "else". You can just assume that even if you don't write it "else don't do anything" is actually there.

Basically an "if" is a splitter, and the CPU pre-load instructions, so when it comes to a split (if or if-else, basically the same thing) it needs to decide which branch's instructions to pre-load. If it guesses wrong, then it has to throw out the pre-load data. The compiler can't determine what your code is meant to do, so what it does is just picks the "if" part as the default behavior, and the "else" part (even if it's just implied) as the aberrant behavior.

Code: [Select]
// this code is slow

if(rare_thing_happened) // compiler thinks you're saying "rare thing" is the most likely outcome
{
   message("Rare error happened");
}
else
{
   do_normal_thing();
}

// vs this which is faster, as long as rare_thing really is rare:

if(! rare_thing_happened) // not rare thing - you've told the compiler that rare thing is less common
{
   do_normal_thing();
}
else
{
   message("Rare error happened");
}

This sort of thing is a really basic level of optimization: just being aware of some hardware/compiler quirks so that you can default to writing faster code to start with.
« Last Edit: October 26, 2016, 03:53:11 pm by Reelya »
Logged

wierd

  • Bay Watcher
  • I like to eat small children.
    • View Profile
Re: Coding for absolute beginners?
« Reply #35 on: October 26, 2016, 04:26:09 pm »

I have actually seen a compiler ( old GCC. Nobody uses it now.) Get confused when the condition to check is very complex. (Logical return from several parentheticals.)

Have not seen in awhile.

Mostly, I was suggesting the more structured decision block for future proofing, and ease of the programmer.
Logged

i2amroy

  • Bay Watcher
  • Cats, ruling the world one dwarf at a time
    • View Profile
Re: Coding for absolute beginners?
« Reply #36 on: November 01, 2016, 07:43:28 pm »

Another thing to keep in mind when doing if-else is that if is faster than else. That includes times you didn't actually write the "else". You can just assume that even if you don't write it "else don't do anything" is actually there.
Is that really true? It seems to me that the overhead at the actual assembly level is going to either be "do the instructions + goto the ending point" for the if or is going to be "goto the "else clause + do instructions (and intrinsically end up at the ending point when finished)". Both cases seem like they would resolve down to only a single goto's worth of overhead regardless of if I do the goto before the instructions for the else case or do it afterwards for the if case.

The only times when that seems like it wouldn't be true would be if you had 3+ cases (if, elseif, else), in which case case 1 only requires checking 1 thing to get to, while case two would require 2 checks, and so forth.
Logged
Quote from: PTTG
It would be brutally difficult and probably won't work. In other words, it's absolutely dwarven!
Cataclysm: Dark Days Ahead - A fun zombie survival rougelike that I'm dev-ing for.

wierd

  • Bay Watcher
  • I like to eat small children.
    • View Profile
Re: Coding for absolute beginners?
« Reply #37 on: November 01, 2016, 09:05:41 pm »

Its a cache contention issue.  On a conditional branch (if then), the CPU needs to predict which path will execute in a probabilistic manner. It makes sense to assume that the default (programmer expected) code path will be the true conditional side of the branch. So, the CPU will keep code and data associated with that side of the branch in cache. Otherwise, it invalidates the cache, loafs the correct code path and data structures, and resumes execution. This fetching cycle is expensive, aka, slower.
Logged

Starver

  • Bay Watcher
    • View Profile
Re: Coding for absolute beginners?
« Reply #38 on: November 02, 2016, 08:39:05 am »

Or just:
Code: [Select]
0123: ... something_to_always_do_before_test
0124: ... something_else_to_always_do_before_test
0125: CMP test_one_thing against_another_thing
0126: JNE 013A
0127:   ... something_to_do_if_test_was_equal
0128:   ... something_else_to_do_if_test_was_equal
0129: JMP 013C
013A:   ... something_to_do_if_test_wasn't_equal
013B:   ... something_else_to_do_if_test_wasn't_equal
013C: ...  something_to_always_do_after_test
If there's a processor lookahead, maybe it likely speculates that, after 0125's question, the 0126 decision means that 0128 and 0129's hard-coded* jump to 013C will happen most of the time, rather than 013A, 013B and 'out' and onward through 013C.

OTOH, there might actually be a pre-processor preference for the Jump Non-Equal, and the compiler likes to make use of that.  By missing the straight Jump in this particular example, one less instruction needs processing, which is as good a reason as any for an assembler-writer or machine compiler to take the assumed preference of the higher-level coder as dictated to by "if(test) then {likely things} else {unlikely things}" and reverse it (use Jump Equal instead of Jump Non-Equal, if necessary).

Certainly, without any assumption of forward-looking, I'd have written it to prefer the "assembly else" branch. Especially if it was a "one thing or nothing".  Write it instead as "nothing or one thing", i. e. "if (not_bother) { /* nothing */ } else { do_bother }; continuation_stuff.." in high-level (wasteful and confusing!) but the directly related low-level would be something like "CMP foo bar; JNE CONTINUATION; do_bother; CONTINUATION: continuation_stuff"...  You always have to do the JNE (or JE,  or functionally equivalent JNZ/JZs, according to need and preference) and you save yourself a JE followed by a JMP followed by the Equal code that the Notequal routing version misses out if you just do JNE to where the JMP would have gone followed by the equal code...   IYSWIM.


* Assuming you don't rewrite the JMP parameter, elsewhere, as part of a more nebulous code-flow that probably trips up any pre-processor  ;)


ETA: ...erm. But that's a bit old-school. I don't do so much assembler myself, these days, and it probably means nothing to most people.  (Or else they wish it means nothing!)
« Last Edit: November 02, 2016, 08:41:25 am by Starver »
Logged

Reelya

  • Bay Watcher
    • View Profile
Re: Coding for absolute beginners?
« Reply #39 on: November 02, 2016, 09:54:08 am »

In some cases they do a thing called "branch predication", in that, both branches are computed, but depending on the value of the branch decision, one of the maths results gets thrown out afterwards. This allows them to avoid the cost associated with guessing wrong, by delaying the decision. But this is only possible when what's done by the "if" statement on both branches is extremely simple.

Draignean

  • Bay Watcher
  • Probably browsing tasteful erotic dolphin photos
    • View Profile
Re: Coding for absolute beginners?
« Reply #40 on: November 02, 2016, 11:48:50 am »

In some cases they do a thing called "branch predication", in that, both branches are computed, but depending on the value of the branch decision, one of the maths results gets thrown out afterwards. This allows them to avoid the cost associated with guessing wrong, by delaying the decision. But this is only possible when what's done by the "if" statement on both branches is extremely simple.

How simple is simple enough is actually a really fun problem, and it varies depending on what you're doing. Graphics cards, for instance, have such insane parallelization that a lot the languages used to code for them will do everything (regardless of branch length) and throw away what is unneeded.

Granted, on less absurdly parallel systems (like your normal hardware), flushing the pipe is more expensive.

Its a cache contention issue.  On a conditional branch (if then), the CPU needs to predict which path will execute in a probabilistic manner. It makes sense to assume that the default (programmer expected) code path will be the true conditional side of the branch. So, the CPU will keep code and data associated with that side of the branch in cache. Otherwise, it invalidates the cache, loafs the correct code path and data structures, and resumes execution. This fetching cycle is expensive, aka, slower.

Of course, a lot of this depends on what language you're using. If(Unexpected)  [...]; Else [...]; is GPP, but it's also not terrible advantageous unless the language you're writing in is optimized for optimization. Optimizing Java at that level is like putting lipstick on a pig, but for something like C/C++ it's a sensible and important decision.

Logged
I have a degree in Computer Seance, that means I'm officially qualified to tell you that the problem with your system is that it's possessed by Satan.
---
Q: "Do you have any idea what you're doing?"
A: "No, not particularly."

nenjin

  • Bay Watcher
  • Inscrubtable Exhortations of the Soul
    • View Profile
Re: Coding for absolute beginners?
« Reply #41 on: November 02, 2016, 06:49:49 pm »

This might work: http://www.roguebasin.com/index.php?title=Complete_Roguelike_Tutorial,_using_python%2Blibtcod

Just wanted to thumbs up this. Within three days of working with it I had a playable if short text-based adventure game with simple logic and choices. Within that time I'd mined everything out of the tutorial and started in on random number generation in Python for combat.
Logged
Cautivo del Milagro seamos, Penitente.
Quote from: Viktor Frankl
When we are no longer able to change a situation, we are challenged to change ourselves.
Quote from: Sindain
Its kinda silly to complain that a friendly NPC isn't a well designed boss fight.
Quote from: Eric Blank
How will I cheese now assholes?
Quote from: MrRoboto75
Always spaghetti, never forghetti
Pages: 1 2 [3]