Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added farms (partial fix of the issue #86) #140

Merged
merged 9 commits into from
Feb 3, 2022
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ jar{
// Resolves the input problem during Gradle run
run{
standardInput = System.in
}
}
77 changes: 77 additions & 0 deletions src/com/hotmail/kalebmarc/textfighter/farm/Crop.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.hotmail.kalebmarc.textfighter.farm;

import com.hotmail.kalebmarc.textfighter.main.Ui;
import com.hotmail.kalebmarc.textfighter.player.Achievements;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused import

import com.hotmail.kalebmarc.textfighter.player.Coins;
import com.hotmail.kalebmarc.textfighter.player.Stats;
import com.hotmail.kalebmarc.textfighter.player.Xp;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused import


import java.util.ArrayList;

public class Crop {
public static final ArrayList<Crop> cropArrayList = new ArrayList<Crop>();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is implicit and not actually needed

Suggested change
public static final ArrayList<Crop> cropArrayList = new ArrayList<Crop>();
public static final ArrayList<Crop> cropArrayList = new ArrayList<>();


private String name;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these three variables can be final

private int sellPrice;
private Seed seed;

private int owned = 0;

public Crop(String name, int sellPrice, Seed seed, boolean firstInit, boolean changeDif) {
this.name = name;
this.sellPrice = sellPrice;
this.seed = seed;

if (!changeDif) {
cropArrayList.add(this);
}

if (firstInit) {
this.owned = 0;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is already set as 0 in the declaration on line 18

}
}

public void sell(int piecesSold){
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public void sell(int piecesSold){
public void sell(int piecesSold) {

int totalPrice = sellPrice * piecesSold;

Coins.set(totalPrice, true);
Stats.coinsGainedOnCrops += totalPrice;
this.owned -= piecesSold;
Ui.println("You have sold " + this.getName() + " (" + piecesSold + " bundles)" + " for " + totalPrice + " coins.");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't have to do it this way, but an alternative could be

Ui.println(String.format("You have sold %s (%s bundles) for %s coins.", this.getName(), piecesSold, totalPrice));

Ui.println("You currently have " + this.owned + " bundles of " + this.getName());
Ui.println("Coins: " + Coins.get());
Ui.pause();
}

public static ArrayList<Crop> getCrops() {
return cropArrayList;
}
public String getName() {
return name;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for these non-static functions, you should use the this keyword when accessing class variables. Although it technically works this way, it's good practice to use this. It makes it clearer and less error-prone if these functions ever got more complex in the future!

Suggested change
return name;
return this.name;

}
public int getSellPrice() {
return sellPrice;
}
public int getOwned() {
return owned;
}
public void setOwned(int owned, boolean add) {
if (add) {
this.owned += owned;
} else {
this.owned = owned;
}
}

public void viewAbout() {
Ui.cls();
Ui.printhr();
Ui.println(Ui.getCentred(this.name.toUpperCase()));
Ui.println();
Ui.println("Sell price: " + this.sellPrice + " coins");
Ui.println("Seed: " + this.seed.getName());

Ui.printhr();
Ui.pause();
}
}
146 changes: 146 additions & 0 deletions src/com/hotmail/kalebmarc/textfighter/farm/Farm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package com.hotmail.kalebmarc.textfighter.farm;

import com.hotmail.kalebmarc.textfighter.main.Ui;
import com.hotmail.kalebmarc.textfighter.player.Achievements;
import com.hotmail.kalebmarc.textfighter.player.Coins;
import com.hotmail.kalebmarc.textfighter.player.Stats;
import com.hotmail.kalebmarc.textfighter.player.Xp;

import java.util.ArrayList;
import java.util.Locale;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused import


public class Farm {

public static final ArrayList<Farm> arrayFarm = new ArrayList<Farm>();

private String name;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all these (except owns) can be final

private int price;
private int level;
private String description;

private int fieldCount;
private ArrayList<Field> fields = new ArrayList<Field>();

private boolean owns;

public Farm(String name, String description, int price, int level, int fieldCount, boolean firstInit, boolean changeDif) {
this.name = name;
this.price = price;
this.level = level;
this.description = description;

this.fieldCount = fieldCount;
for (int i = 0; i < fieldCount; i++) {
fields.add(new Field());
}

if (!changeDif) {
arrayFarm.add(this);
}

if (firstInit) {
this.owns = false;
}
}

public static ArrayList<Farm> getFarms() {
return arrayFarm;
}
public String getName() {
return name.toString();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name is already a String, no need to call .toString()

}
public int getPrice() {
return price;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as the other comment said, this should have this.

}
public int getLevel() {
return level;
}
public int getFieldCount() {
return fieldCount;
}
public ArrayList<Field> getFields() {
return fields;
}

public void menu() {
while (true) {
Ui.cls();
Ui.printhr();
Ui.println(Ui.getCentred("Welcome to " + name + "!"));
Ui.println();
Ui.println("Fields:");
for (int i = 0; i < fieldCount; i++) {
Ui.print((i + 1) + "): ");

Seed seed = fields.get(i).getSeed();
Ui.print("(" + ((seed == null) ? "No seeds planted)" : seed.getName() + ") - "));
Ui.println((seed == null) ? "" : ((fields.get(i).getRemainingTime() > 0) ? fields.get(i).getRemainingTime() + " fights remaining until the harvest." : "Ready for harvest"));
}
Ui.println();
Ui.println((fieldCount + 1) + ") Back");

int menuItem = Ui.getValidInt();
if (menuItem == fieldCount + 1) {
Ui.cls();
return;
}

if (menuItem <= fieldCount) {
fields.get(menuItem - 1).menu(this, menuItem);
} else {
Ui.println();
Ui.println(menuItem + " is not an option.");
Ui.cls();
Ui.pause();
}
}
}

public boolean owns() {
return owns;
}
public void buy() {
if (this.owns()) {
Ui.msg("You already own this property.");
return;
}
if (level > Xp.getLevel()) {
Ui.msg("You do not have a high enough level to buy this item.");
return;
}
if (price > Coins.get()) {
Ui.msg("You do not have enough coins to buy this item.");
return;
}

Achievements.boughtItem = true;
Coins.set(-price, true);
Stats.coinsSpentOnProperty += price;
this.owns = true;
Ui.println("You have bought a " + this.getName() + " for " + this.price + " coins.");
Ui.println("Coins: " + Coins.get());
Ui.pause();

}

public void updateFields() {
for (Field f : fields) {
f.updateCycle();
}
}

public void viewAbout() {
Ui.cls();
Ui.printhr();
Ui.println(Ui.getCentred(this.name.toUpperCase()));
Ui.println(Ui.getCentred(this.description));
Ui.println();
Ui.println("Price: " + this.price + " coins");
Ui.println("Required level: " + this.level);
Ui.println("Number of fields: " + this.fieldCount);

Ui.printhr();
Ui.pause();
}
}

130 changes: 130 additions & 0 deletions src/com/hotmail/kalebmarc/textfighter/farm/Field.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.hotmail.kalebmarc.textfighter.farm;

import com.hotmail.kalebmarc.textfighter.main.Random;
import com.hotmail.kalebmarc.textfighter.main.Ui;

import java.util.ArrayList;

public class Field {
private Seed seed;
private int remainingTime;

public Seed getSeed() {
return seed;
}

public void menu(Farm farm, int fieldNr) {
while (true) {
// int i = 1;
Ui.cls();
Ui.printhr();
Ui.println(Ui.getCentred("Field " + fieldNr + " (" + farm.getName() + ") "));
Ui.print("(" + ((seed == null) ? "No seeds planted)" : seed.getName() + ") - "));
Ui.println((seed == null) ? "" : ((this.getRemainingTime() > 0) ? this.getRemainingTime() + " fights remaining until the harvest." : "Ready for harvest"));
Ui.println();
// Can you think of any way I could possibly make this work? I wanted to make the menu dynamic - display the harvest option only if the crops are ready for harvest - but I just can't come up with a universal and scalable way to solve this other than bunch of if-else statements, which is rather bulky and doesn't meet either specified requirement.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the first comment.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately I couldn't think of a clean way of doing this without getting into some much more advanced stuff (a seperate helper class that can take an array of functions/items, and dynamically display them in order without any hard-coded number). I think a few if statements is good enough in this case. This is what I got (similar to yours): ``` boolean readyToHarvest = false;

print("1) Plant Seeds");
if (readyToHarvest) print("2) Harvest");
print(readyToHarvest ? "3" : "2" + ") Back");

switch (getValidInt()) {
  case 1:
    plant();
    return;
  case 2:
    if (readyToHarvest) {
      harvest();
      return;
    } else {
      print("quit!");
      return;
    }
  case 3:
    if (readyToHarvest) {
      print("quit!");
      return;
    }
  default:
    print("fallback");
}```

(Done in a sandbox test environment, would need tweaking to work in this codebase)


For the situation where there are an unknown amount of extra options, theres an example of how this could be done here:

for (int i = 0; i < Weapon.getWeapons().size(); i++) {

although its not really a clean solution either.

If there was to be some nice automated menu-builder classs, that should be done on a seperate PR/issue since it would be a pretty big project & would include converting all the old menus to use the new helper class

// if (remainingTime == 0) {
// Ui.println(i + ") Harvest");
// i++;
// }
// Ui.println(i + ") Plant seeds");
// i++;
// Ui.println(i + ") Back");
//
// int menuItem = Ui.getValidInt();
// int cond = i - menuItem;
// switch (cond) {
// case 0:
// return;
// case 1:
// if (remainingTime == 0) {
// // ...
// }
// }
Ui.println("1) Plant seeds");
Ui.println("2) Harvest");
Ui.println("3) Back");

int menuItem = Ui.getValidInt();

switch (menuItem) {
case 1:
plantSeed();
return;
case 2:
harvest();
case 3:
return;
default:
Ui.println("\"" + menuItem + "\" isn't a valid option.");
Ui.pause();
}
}
}

public void plantSeed() {
ArrayList<Seed> validSeeds = new ArrayList<>();

Ui.cls();
Ui.println("Which seeds would you like to plant?");
Ui.println();
for (int i = 0; i < Seed.getSeeds().size(); i++) {
Seed s = Seed.getSeeds().get(i);
if (s.getOwned() > 0) {
validSeeds.add(s);
Ui.println((i + 1) + ") " + s.getName());
}
}
Ui.println((validSeeds.size() + 1) + ") Back");

int menuItem = Ui.getValidInt();
if (menuItem == validSeeds.size() + 1) {
return;
}
Seed s = validSeeds.get(menuItem - 1);

s.setOwned(-1, true);
this.seed = s;
remainingTime = s.getGrowthTime();

Ui.cls();
Ui.println("You have planted " + s.getName() + " on this field.");
Ui.println("There are " + s.getOwned() + " bundles of " + s.getName() + " remaining in your inventory.");
Ui.pause();
}

public void harvest() {
if (seed == null) {
Ui.cls();
Ui.println("No seeds have been planted yet!");
Ui.pause();
return;
}
if (remainingTime > 0) {
Ui.cls();
Ui.println("The crops haven't fully matured yet!");
Ui.pause();
return;
}

Crop c = seed.getCrop();
int yield = Random.RInt(seed.getMinCrops(), seed.getMaxCrops());
c.setOwned(yield, true);
this.seed = null;

Ui.cls();
Ui.println("The harvest has yielded " + yield + " bundles of " + c.getName() + ".");
Ui.println("You currently have " + c.getOwned() + " bundles of " + c.getName() + ".");
Ui.pause();
}

public void updateCycle() {
if (!(remainingTime <= 0)) {
remainingTime--;
}
}

public int getRemainingTime() {
return remainingTime;
}
}
Loading