Harvest – A highly customisable farming script

I think eegee's fix was for rain doh wasn't it? I'll have a closer look in a bit. For the 441 error, I added the code you posted (post 326, or something close to it, I think) and it seems to be working fine. The 462 cookie error is a bit weird, and quite hard to test for without more information. I'd be interested to know if Icon's still seeing that issue, or if anyone else's run into it (I've certainly never seen it). Thanks Theraze :-)

Can anyone tell me about the "unreachable code" warning that mafia now outputs before running Harvest? It was something that a new version of mafia introduced shortly after I stopped active development of Harvest and I never got around to looking into it.
 
Unreachable code means you've got something that's a bit sloppy in ASH, though it might be 'best practice' for some other language. Things like switch (something) { case 1: return; break; default: break; } are unreachable, since the "break" in case 1 is after you've already returned out of the function...

At this point, it's still just a warning. We've been told that it will probably become a script-aborting error at some time soonish, since we've had a major revision or two since.
 
Sweet, that's an easy fix. I should probably get rid of the switch statements entirely; I've been told never to use them in C (though I don't know what conventional wisdom says about other languages). I see the point, but they do have a certain elegance about them so for now I'll keep them.
 
Thee is nothing wrong with switch statements. I have no idea who told you to "never use them in C", but, as a C programmer who uses switch statements all the time, I instantly do not trust that person.

You are welcome to decide who you trust.

:)
 
It's not just switch statements, and they aren't intrinsically bad... that same example is fine if you turn it into switch (something) { case 1: return; default: break; } which makes it not have a break that's unreachable. Anytime you have a return with stuff after it, that will give you unreachable code. :)
 
OK, "never" was a bit strong, his exact words were "Rarely useful. Not usually recommended." As I said, I see the argument both ways.

I opted to store the result in a variable and just return it at the end (I based that decision on the premise that one return statement per function is generally neater than three).

PHP:
int num_ducks()
	{
	/* Returns the number of ducks you can fight each day */
	announce(2, "num_ducks");
	
	int num = 5;
	
	switch (get_property("sidequestFarmCompleted"))
		{
		case "fratboy":
			num = 15;
			break;
		case "hippy":
			num = 10;
			break;
		}
	
	return num;
	}
 
Not having unreachable code has nothing to do with not using switch statements. It just involves recognizing how control flow works in your language of choice and not wasting your time and keystrokes inserting statements that will never be executed.

I do not accept that:

Code:
case xxx:
    return 1;
    break;
is good style, ever. No, the claim that people are actual taught to code like that makes no sense. To me, it tells me that the person who teaches that "style" understands neither machine architecture nor compilers. It's just stupid to claim that coding like that is "better" in any way whatsoever.

Your teachers told you to code like that?
Your teachers suck.

I make this claim from the certain knowledge that I am a better programmer than any computer programming professor that I have ever met.

Live with it.
 
I think there may have been a misunderstanding here. The advice to me was to, in general, avoid switch statements. This code:
Code:
case xxx:
    return 1;
    break;
Was my own bad style and had nothing to do with what I've been taught. In fact, I wrote that function before I'd been taught any C at all (which is probably the source of the problem), so my lecturer goes blameless in this instance :) So no, I wasn't told to code like that, and I feel bad for incurring your ire towards my lecturer, who is in fact a lovely person and a good programmer.

Personally I don't think that titles like "professor" and "doctor" have much to do with how well you code, write, build bridges or otherwise perform in your chosen profession. People's ideas should stand on their own merit and titles don't improve the quality of one's thought processes :P

Now I'm interested to know how you'd implement the function I posted above. What looks neatest to your eyes?
 
Thee is nothing wrong with switch statements. I have no idea who told you to "never use them in C", but, as a C programmer who uses switch statements all the time, I instantly do not trust that person.

You are welcome to decide who you trust.

:)

I know that some languages* have performance issues switching on strings - Java itself did not even offer it as an option until 1.7. Speaking from ignorance, I imagine ASH resolves them to if else branches under the hood, so it's strictly more attractive code to just use switches.

*not C, I'd imagine, so I'm not really sure what the point of this post was.
 
OK, I've worked eegee's Rain-Doh fix into the script with some cosmetic alterations. Hopefully it all still works :O I've changed the nomenclature from "puttyfarming" and such to "copyfarming". That change has been applied to function names but not to Harvest's settings or properties (that's a headache for another day).

I left out the "recommended VoA" feature because I'm not convinced that it actually gives the best VoA setting possible, and it's not what I had in mind when I wrote Harvest. I wanted to make a script that made it as easy as possible to implement a given farming strategy and that gave you useful statistics about that strategy, not a script that mindlessly (if cleverly) botted in the most optimal way possible. Not that recommending a VoA setting is mindless botting, but it's the sort of inch-mile/slippery slope thing I want to avoid. Make sense? Feel free to argue with me, I'm happy to change my mind if anyone can provide a well conceived argument :).

Finally, I've added a link to the last stable build of Harvest, so that if I roll a buggy update there's always an easy way to downgrade :).

@roippi: That's interesting! I'm assuming you work mainly in Java? Do you use switch statements, then, or just stick to if/else blocks normally?

Can someone please reassure me that initialised variables in ash always default to meaningful values like 0, 0.0, and false? After the little bit of C I've just seen I feel as though I shouldn't take anything for granted.
 
@roippi: That's interesting! I'm assuming you work mainly in Java? Do you use switch statements, then, or just stick to if/else blocks normally?

I think I've coded a grand total of 2 things that were 1.7-spec; everything else has been 1.6 or lower. So I don't think I've ever written a string switch statement in Java. It would feel weird.

You can often get around this by avoiding strings entirely; if all states are known at compile-time, you can just use an Enum like Veracity did here. Java has no problem with those in switch statements (1.5 and later).

Can someone please reassure me that initialised variables in ash always default to meaningful values like 0, 0.0, and false? After the little bit of C I've just seen I feel as though I shouldn't take anything for granted.

They do. There is no such thing as null in ASH.
 
Last edited:
I haven't met enums before. Are they are a Java thing, or a wider programming paradigm that I haven't met yet? I haven't done any coding in Java, though I suppose ash is as little Javaesque isn't it?
 
I haven't met enums before. Are they are a Java thing, or a wider programming paradigm that I haven't met yet?

C (and most modern languages) have enums as well, though Java's are significantly more feature-rich. In Java, the Enum type guarantees sortability, iterability, and some nifty accessory methods like access to the actual variable name.

wiki link
 
Ah OK. So the idea of an enum is to avoid 'magic numbers' by neatening up code like this: card.suit = "clubs" so that it looks like this: card.suit = CLUBS, is that right? Excuse my syntax, I'm guessing :).
 
Sort of. In the basic sense, yes, they are a way to define a constant. But you can just do that by declaring a String or Integer constant and naming it CLUBS as well.

Where enumerations shine is in the fact that you are essentially declaring a whole new type. This means that some things that were legal at compile-time when you were using a String constant are now illegal - which is a good thing. Consider:

Code:
public static final String CLUBS = "clubs";
public static final String DIAMONDS = "diamonds";
public static final String HEARTS = "hearts";
public static final String SPADES = "spades";

public boolean suitIsRed( String suit )
{
    if ( suit.equals( SPADES ) || suit.equals( CLUBS) ) return false;

    return true;
}

That works fine. But what if you later do suitIsRed( "Armani" )? You get true. That's a nonsense answer, and that happened because you allowed any old string to go into your function. Instead, use an Enum and then your function has a different signature:

Code:
public boolean suitIsRed( Suit suit )
{
    switch( suit )
    {
        case SPADES:
        case CLUBS:
              return false;
        default:
              return true;
    {
}

Now you are type-safe: only Suits that you defined in your Suit enumeration are valid arguments to the function.
 
Just on the topic of switches, they're awesome, misunderstood and under appreciated.

In some languages (C and Java included) a switch case will fall through to the next case unless you break it. This can be a pitfall for those new to the language, which is possibly why some would suggest you avoid it.

I could go into more detail about the advantages of using a switch statement, but when I was looking for concise examples to give I found that the wikipedia article covers it nicely.
 
@roippi: It's not nonsensical if you have a red Armani suit :P (Coding jokes are the best). Yep, I think I see the point now, thanks :)

@Catch: Do you have any idea of how often they're used in the wider world? I have no idea what sort of work you do, whether you code for a living or as a hobby, but I'd be interested to know what the norm in industry is, or even if there is one.
 
@Catch: Do you have any idea of how often they're used in the wider world? I have no idea what sort of work you do, whether you code for a living or as a hobby, but I'd be interested to know what the norm in industry is, or even if there is one.

No norm that I have seen in 30+ years of professional experience. Most places don't care, as long as the code works and can be maintained or they have some kind of coding standard that enforces or suggests when to use something and when to avoid it. I'd say that in my own coding it depends upon how many things are involved and how likely it is that I would add more. How I want to handle something unexpected is also a factor. I personally would switch from an if then else structure to a case/switch once I have four items. I would start with a case/switch if I expected to be adding things in the future. If finding something unexpected is an error and I am working in an environment that prefers only one return from a routine then I gravitate towards if then elses, but if multiple returns or what seems to be an abrupt change in control are not a problem then I'm back to case/switch. Bottom line then, in practice is that "It depends".
 
Do you have any idea of how often they're used in the wider world? I have no idea what sort of work you do, whether you code for a living or as a hobby, but I'd be interested to know what the norm in industry is, or even if there is one.

I would like to say that the industry norm is to write clear and concise code whenever possible, which would mean using a switch statement whenever it makes sense to do so. Of course, anyone who has ever been placed in a position of maintaining existing code will tell you how untrue that statement is. Unfortunately, depending on what line of work you're in, a lot of code floating around out there is written by self-taught dabblers who might be woefully unaware of correct coding conventions.

If you're trying to get into good habits, remember that code clarity is a very important aspect of your code (unless you're competing in an obfuscation contest or something :p). If you're working in a particular language for the first time, make yourself aware of all the available control structures before you sink your teeth into it. Understand what a particular control structure is useful for, that way you'll always be using the best tool for the job.
 
Back
Top