• Welcome to the new COTI server. We've moved the Citizens to a new server. Please let us know in the COTI Website issue forum if you find any problems.
  • We, the systems administration staff, apologize for this unexpected outage of the boards. We have resolved the root cause of the problem and there should be no further disruptions.

T5 Spec Cargo

robject

SOC-14 10K
Admin Award
Marquis
I'm designing the speculative cargo code.

I don't want it to be too clever, but I need it to handle the rules.

I think building the cargo is easy, and in fact it seems like a CargoBuilder is in order here. Let me give you an example.

Speculative cargo in Traveller is sold based on the source world's trade codes, and potentially other modifiers (like whether or not a broker is available and contracted for example). If I packed all of this into a constructor, it would be a big honking constructor. On the other hand, a Builder pattern lets me chunk construction into e.g. chained methods ("fluent interface").

Code:
Cargo cargo = CargoBuilder.newCargo().isNa().isRi().build();

In fact, I should be doing this with world data, ship data, and player data as well, but I currently don't.

Of course it won't work that way. It will iterate over trade code strings.
I could just hand the trade codes in a string to the builder.

Code:
Cargo cargo = CargoBuilder.build( "Na Ni Po De" );
 
Last edited:
Next is the also-interesting problem of how to sell cargo in T5.

T5 cargo speculation is a child of Merchant Prince. This means there is a matrix of price modifiers, mapping source trade codes to destination trade codes. In other words, for each trade code the cargo has, are a few trade codes that might affect the selling price up or down.

If that sounds like a Strategy Pattern to you, then maybe I'm going in the right direction.

Wikipedia said:
a class that performs validation on incoming data may use the Strategy pattern to select a validation algorithm depending on the type of data, the source of the data, user choice, or other discriminating factors.

When it all comes down to it, there are only a dozen trade codes that affects a piece of cargo, so therefore there are, at most, a dozen strategies that can apply to it. Additionally, those dozen strategies are customized based on the destination world. SO again we have Builders.

* the first builder builds Strategies for the unit of cargo based on its source world's trade codes.
* the second builder builds Strategies based on the trade codes, each with proper value modifications based on the destination world's trade codes.

I suppose this means that these strategies are parametric... the first builder "activates" some and "deactivates" the others, based on the source TCs, while the second builder does the same thing, using the destination TCs.

I'll have to think about it.
 
Last edited:
I could just hand the trade codes in a string to the builder.

Code:
Cargo cargo = CargoBuilder.build( "Na Ni Po De" );

That's how I been doing it. Passing the Trade Codes. I also have some patron-invoked rare-luxury items to sell/buy that have nothing to do with the trade codes. But only if there is a patron at that location (they travel around at sometimes, and might even be in low passage during the computer's search for them (so no business at the moment for Travellers)).
 
my technique was to pass in the world object, which had the trade codes as essentially calculated (non-DB stored) based on the game version, and trade returned version-specific available cargoes in a standardized way.

This is c# so looked like:

Code:
List<Cargoes> cargoes = loadCargo(world);

where the Cargoes object has tonnage, base price, modified price and a few other bits and pieces (literally - I threw in the BITS cargo string and when printing the cargo manifests included that. Unless someone had steward they did not know to look in the hazards section...) World has UWP and all that, and different version could have different trade codes and all that. I kinda got carried away...
 
my technique was to pass in the world object, which had the trade codes as essentially calculated (non-DB stored) based on the game version, and trade returned version-specific available cargoes in a standardized way.

This is the approach I would take as well. Have the cargo builder pull the information it needs from the world object. Rather than pulling parts from the world data.
 
Yep, that's what I eventually did.

First I created a CargoBuilder, which creates the Cargo and builds up a list of TradeCode flyweights into it, based on the source World.

Then on the other end there's a TradeBuilder, which creates a Trade object that refers to the Cargo, and builds up a list of TradeCodes that apply per code. Once that's done, the sale price is 5000 + list.size * 1000 * (0.1 * TL delta).
 
If you are asking for an opinion of:
Code:
Cargo cargo = CargoBuilder.newCargo().isNa().isRi().build();
vs.
Code:
Cargo cargo = CargoBuilder.build( "Na Ni Po De" );

Then my opinion is option #2, because I think it will be easier to expand it into new world codes. Those strings could easily be in a configuration file, and then you would only need to update that file to get more world codes. If you go with option #1 all such changes will require changes to your Java code.

Joshua
 
I don't know if over-loading or self-modifying code is allowed in Java, but I see that being a way to do option #1. Makes for more challenging programming for not much gained though over option #2, which seems the lazy way out but allows for easy configuring at any time.
 
Back
Top