* @param cs A <code>ChangeSet</code> to update.
     * @param colony A <code>Colony</code>, or <code>null</code>.
     * @param disaster A <code>Disaster</code> value.
     * @return A list of <code>ModelMessage</code>s, possibly empty.
     */
    public List<ModelMessage> csApplyDisaster(Random random, ChangeSet cs, Colony colony, Disaster disaster) {
        logger.finest("Applying effects of disaster " + disaster.getId());
        List<Effect> effects = new ArrayList<Effect>();
        switch(disaster.getNumberOfEffects()) {
        case ONE:
            effects.add(RandomChoice.getWeightedRandom(logger, "Get effects of disaster",
                                                      random, disaster.getEffects()));
            break;
        case SEVERAL:
            for (RandomChoice<Effect> effect : disaster.getEffects()) {
                if (Utils.randomInt(logger, "Get effects of disaster", random, 100)
                    < effect.getProbability()) {
                    effects.add(effect.getObject());
                }
            }
            break;
        case ALL:
            for (RandomChoice<Effect> effect : disaster.getEffects()) {
                effects.add(effect.getObject());
            }
        }

        List<ModelMessage> messages = new ArrayList<ModelMessage>();
        for (Effect effect : effects) {
            if (colony == null) {
                // currently, the only effects that can apply to the
                // player itself are production modifiers
                for (Modifier modifier : effect.getModifiers()) {
                    if (modifier.getDuration() > 0) {
                        Modifier timedModifier = Modifier
                            .makeTimedModifier(modifier.getId(), modifier, getGame().getTurn());
                        cs.addFeatureChange(this, this, timedModifier, true);
                    } else {
                        cs.addFeatureChange(this, this, modifier, true);
                    }
                }
            } else {
                if (Effect.LOSS_OF_MONEY.equals(effect.getId())) {
                    int plunder = Math.max(1, colony.getPlunder(null, random) / 5);
                    modifyGold(-plunder);
                    cs.addPartial(See.only(this), this, "gold");
                    messages.add(new ModelMessage(ModelMessage.MessageType.DEFAULT,
                                                  effect.getId(), this)
                                 .addAmount("%amount%", plunder));
                } else if (Effect.LOSS_OF_GOODS.equals(effect.getId())) {
                    Goods goods = Utils.getRandomMember(logger, "select goods",
                                                        colony.getLootableGoodsList(), random);
                    goods.setAmount(Math.min(goods.getAmount() / 2, 50));
                    colony.removeGoods(goods);
                    messages.add(new ModelMessage(ModelMessage.MessageType.DEFAULT,
                                                  effect.getId(), this)
                                 .addName("%goods%", goods));
                } else if (Effect.LOSS_OF_UNIT.equals(effect.getId())) {
                    Unit unit = getUnitForEffect(colony, effect, random);
                    if (unit != null) {
                        if (colony.getUnitCount() == 1) {
                            csDisposeSettlement(colony, cs);
                            messages.add(new ModelMessage(ModelMessage.MessageType.DEFAULT,
                                                          "model.disaster.effect.colonyDestroyed", this)
                                         .addName("%colony%", colony));
                        } else {
                            cs.addDispose(See.perhaps().always(this),
                                          unit.getLocation(), unit);
                            messages.add(new ModelMessage(ModelMessage.MessageType.DEFAULT,
                                                          effect.getId(), this)
                                         .add("%unit%", unit.getType().getNameKey()));
                        }
                    }
                } else if (Effect.DAMAGED_UNIT.equals(effect.getId())) {
                    Unit unit = getUnitForEffect(colony, effect, random);
                    if (unit != null && unit.isNaval()) {
                        Location repairLocation = unit.getRepairLocation();
                        if (repairLocation == null) {
                            csSinkShip(unit, null, cs);
                            messages.add(new ModelMessage(ModelMessage.MessageType.DEFAULT,
                                                          "model.disaster.effect.lossOfUnit", this)
                                         .add("%unit%", unit.getType().getNameKey()));

                        } else {
                            csDamageShip(unit, repairLocation, cs);
                            messages.add(new ModelMessage(ModelMessage.MessageType.DEFAULT,
                                                          effect.getId(), this)
                                         .addName("%unit%", unit));
                        }
                    }
                } else {
                    messages.add(new ModelMessage(ModelMessage.MessageType.DEFAULT,
                                                  effect.getId(), this));
                    for (Modifier modifier : effect.getModifiers()) {
                        if (modifier.getDuration() > 0) {
                            Modifier timedModifier = Modifier
                                .makeTimedModifier(modifier.getId(), modifier, getGame().getTurn());
                            cs.addFeatureChange(this, colony, timedModifier, true);
                        } else {
                            cs.addFeatureChange(this, colony, modifier, true);
                        }
                    }
                }
            }
        }
        return messages;
    }