Skip to main content

Hoardomatic Code: Hoard Class

I've decided to start making available the code I've written for my treasure generator in a leisurely fashion. I won't be posting the XML files containing the data (that'd basically be posting the contents of DF8), but I will be putting up some sample files to demonstrate how the raw data is shaped.

This code is very rough, having been composed...let's say, organically, rather than according to a well thought-out plan and good programming principles. It contains much which is incomplete or inefficient. However, it ultimately gives me lists of useful treasures, which is more or less as far as I'm inclined to take things without it turning into something tediously like my day job. However, it may help those who want to pursue something similar.

Briefly, then, I've assembled a mess of Java code to represent bunches of items. The intended entry point is a Hoard object. A hoard contains a bunch of items, which in turn has a number of simple properties (base weight, base cost, name, etc.) and more complex properties representing lists of enchantments, lists of decorative embellishments, and containers, which are themselves items. Going from the top down, I'm starting with the Hoard class.

Hoard


ArrayList<Item> items: A list of items
Double remaining_val: Portion of the hoard's value not made up in items.

The hoard is a pretty simple construct containing a batch of items. The main usage I've implemented for it is a constructor which takes a Double value indicating the desired value of the hoard. Given that, it sets an approximate threshold for the maximum value of the items and randomly adds items to the list until it passes that value. I left some wiggle room in the value of the items so that the hoard-generator wouldn't get itself into an excessively long loop trying to find an item of just the right value to round out the desired total value of the hoard. There's a secondary constructor which takes a target value, a list of required attributes and a list of forbidden attributes. It acts much like the first constructor, but it tests prospective items by making sure they have an attribute on the required list and don't have any attributes on the forbidden list. This is the way to get, say, "the contents of the armory" (by requiring weapons and armor) or "the contents of the giant adventurer-eater's stomach" (by forbidding organic items).

Beyond that, the Hoard class just has a few functions bundling up the total value (necessary to check running progress) and concatenating descriptions of its component items. Here's the code:


package hoardomatic;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;

public class Hoard {

    private ArrayList<Item> items = new ArrayList<Item>(); // item attributes
    private Double remaining_val = 0.0;
   
    public Hoard() {
        // TODO Auto-generated constructor stub
    }
   
    public void setRemaining(Double inval){
        remaining_val = inval;
    }
   
    public Hoard(Double max_value){
       
        Double ceiling_val = max_value * .9;
        while(getHoardValue() < ceiling_val){
            Item test_item = new Item();
            if ((test_item.getFinalCost() + getHoardValue()) < max_value ){
                items.add(test_item);
            }
        }
        remaining_val = max_value - getHoardValue();
    }
   
   
    public void addItem (Item the_item){
        items.add(the_item);
    }
   
    public Hoard(Double max_value, ArrayList<String> req_list, ArrayList<String> forb_list){
       
        Double ceiling_val = max_value * .9;
        while(getHoardValue() < ceiling_val){
            Item test_item = new Item();
            boolean do_add = false;
            if ((test_item.getFinalCost() + getHoardValue()) < max_value ){
                // required attributes
                if (req_list.size() < 1){
                    do_add = true;
                }
               
                for(int a = 0; a < req_list.size() ; a++){
                    if (test_item.isAttribute(req_list.get(a))){
                        do_add = true;
                    }
                   
                    if (req_list.get(a).contentEquals("Shiny")){
                        if (test_item.isAttribute("Jewelry") | test_item.isAttribute("Iron") | test_item.isAttribute("Steel") | test_item.getGems().size() > 0 ){
                            do_add = true;
                        }
                    }
                   
                    if (req_list.get(a).contentEquals("Enchanted")){
                        if (test_item.getEnchantments().length() > 0 ){
                            do_add = true;
                        }
                    }
                }
               
                // forbidden attributes
                for(int b = 0; b < forb_list.size() ; b++){
                    if (test_item.isAttribute(forb_list.get(b))){
                        do_add = false;
                    }
                   
                    if (forb_list.get(b).contentEquals("Shiny")){
                        if (test_item.isAttribute("Jewelry") | test_item.isAttribute("Iron") | test_item.isAttribute("Steel") | test_item.getGems().size() > 0 ){
                            do_add = false;
                        }
                    }
                   
                    if (forb_list.get(b).contentEquals("Enchanted")){
                        if (test_item.getEnchantments().length() > 0 ){
                            do_add = false;
                        }
                    }
                }
            }

            if(do_add){
                items.add(test_item);
            }
           
        }
        remaining_val = max_value - getHoardValue();
    }

   
    public String hoardReport(){
        String full_report = "";
       
        for (Item iLine : items) {
            full_report = full_report + iLine.report() + "\n" ;
        }
       
        NumberFormat fmt = NumberFormat.getCurrencyInstance();
        full_report = full_report + fmt.format(remaining_val) + " in coins.";
       
        return full_report;
       
    }
   
   
    public Double getHoardValue(){
       
        Double total_val = 0.0;
       
        if(items.size() > 0){
            for (Item iLine : items) {
                total_val = total_val + iLine.getFinalCost();
            }
        }
        return total_val;
    }

}



Comments

Popular posts from this blog

Dungeon Fantasy RPG PDFs to Backers!

It is, at long last, out! Sort of! PDFs of the Dungeon Fantasy Roleplaying Game have been released to Kickstarter backers. I don't think it'll be generally available until next month, but since it's in the wild in at least a limited way, I feel I can talk about this a bit more like a customer than someone involved in the project.

The Dungeon Fantasy RPG is a complete fantasy tabletop roleplaying game. It's based on GURPS 4th edition rules, but it's a stand-alone game, requiring no other books, or even prior knowledge of GURPS. I've already made some general comments elsewhere (I got an advanced peek for a number of reasons, not the least of which is that I was called on to write some follow-up material coming out later). I'll expand on that here.

For those unfamiliar with GURPS, it's a point-buy system rather than randomly rolled, class-and-level, or life path, and pretty much everything in play boils down to "try to roll a target number or less o…

Writing GURPS Adventures

Someone over on the forum asked for advice on writing adventures for GURPS. Or more specifically, in context, writing GURPS adventures with an eye towards publication by SJ Games, which is a very different animal. Whatever method and structure you have for writing up adventures for your own use is, of course, the best and you should use it for your own purposes. But we're talking about commerce here, not just art, so this should be thought of as advice on how to do business with a particular publisher, not generally useful advice on how to write adventures.

I need to start by defining a term. SJ Games means something specific by "adventure." As the wish list uses the word, an adventure has a plot, or at least something plot-like in it. It presents a specific problem to solve through a progression of encounters. They are not sandboxes. Sandbox-style adventures, with their multiplicity of possible PC objectives, are, in the terminology of the wish list, locations. There ar…

Doctor GURPS Author, Or How I Learned To Stop Worrying And Love The WYSIWYG Template

Something I see over at the forum from time to time is people saying that they're interested in writing for Pyramid or GURPS but are instantly driven off by the size and complexity of the style guide and the WYSIWYG template. And they can be intimidating documents. They're long and there are some really specific guidelines for certain kinds of material.

And that's necessary. Despite working almost entirely in the realm of the imagination, Steve Jackson Games is a technical publisher. They need to organize information in regular, predictable formats. It's like Safety Data Sheets, just of their own design.

But the thing I've noticed in several years of writing GURPS material is that you won't need most of it.

So if you want to write an article for Pyramid, here's what you do: Once you've gotten a thumb-up from Steven on your proposal, get the template, create a new document based on it (Don't use Microsoft Word? Me neither. I use LibreOffice. The temp…