* @param action The monarch action.
     * @param cs A <code>ChangeSet</code> to update.
     */
    private void csMonarchAction(final ServerPlayer serverPlayer,
                                 MonarchAction action, ChangeSet cs) {
        final Monarch monarch = serverPlayer.getMonarch();
        boolean valid = monarch.actionIsValid(action);
        if (!valid) return;
        String messageId = "model.monarch.action." + action.toString();
        StringTemplate template;
        MonarchActionMessage message;

        switch (action) {
        case NO_ACTION:
            break;
        case RAISE_TAX_WAR: case RAISE_TAX_ACT:
            final int taxRaise = monarch.raiseTax(random);
            final Goods goods = serverPlayer.getMostValuableGoods();
            if (goods == null) {
                logger.finest("Ignoring tax raise, no goods to boycott.");
                break;
            }
            template = StringTemplate.template("model.monarch.action."
                + action.toString())
                .addStringTemplate("%goods%", goods.getType().getLabel(true))
                .addAmount("%amount%", taxRaise);
            if (action == MonarchAction.RAISE_TAX_WAR) {
                template = template.add("%nation%", getNonPlayerNation());
            } else if (action == MonarchAction.RAISE_TAX_ACT) {
                template = template.addAmount("%number%",
                    Utils.randomInt(logger, "Tax act goods", random, 6))
                    .addName("%newWorld%", serverPlayer.getNewLandName());
            }
            message = new MonarchActionMessage(action, template);
            message.setTax(taxRaise);
            askThisTurn(serverPlayer, message,
                new DOMMessageHandler() {
                    public DOMMessage handle(DOMMessage message) {
                        boolean result
                            = (message instanceof MonarchActionMessage)
                                ? ((MonarchActionMessage)message).getResult()
                                : false;
                        raiseTax(serverPlayer, taxRaise, goods, result);
                        return null;
                    }
                },
                new Runnable() {
                    public void run() {
                        raiseTax(serverPlayer, taxRaise, goods, false);
                    }
                });
            break;
        case LOWER_TAX_WAR: case LOWER_TAX_OTHER:
            int oldTax = serverPlayer.getTax();
            int taxLower = monarch.lowerTax(random);
            serverPlayer.csSetTax(taxLower, cs);
            template = StringTemplate.template(messageId)
                .addAmount("%difference%", oldTax - taxLower)
                .addAmount("%newTax%", taxLower);
            if (action == MonarchAction.LOWER_TAX_WAR) {
                template = template.add("%nation%", getNonPlayerNation());
            } else {
                template = template.addAmount("%number%",
                    Utils.randomInt(logger, "Lower tax reason", random, 5));
            }
            cs.add(See.only(serverPlayer), ChangePriority.CHANGE_LATE,
                new MonarchActionMessage(action, template));
            break;
        case WAIVE_TAX:
            cs.add(See.only(serverPlayer), ChangePriority.CHANGE_NORMAL,
                new MonarchActionMessage(action,
                    StringTemplate.template(messageId)));
            break;
        case ADD_TO_REF:
            AbstractUnit refAdditions = monarch.chooseForREF(random);
            if (refAdditions == null) break;
            monarch.getExpeditionaryForce().add(refAdditions);
            template = StringTemplate.template(messageId)
                .addAmount("%number%", refAdditions.getNumber())
                .add("%unit%", refAdditions.getUnitType(getGame().getSpecification())
                     .getNameKey());
            cs.add(See.only(serverPlayer), monarch);
            cs.add(See.only(serverPlayer), ChangePriority.CHANGE_LATE,
                   new MonarchActionMessage(action, template));
            break;
        case DECLARE_PEACE:
            List<Player> friends = monarch.collectPotentialFriends();
            if (friends.isEmpty()) break;
            Player friend = Utils.getRandomMember(logger, "Choose friend",
                friends, random);
            serverPlayer.csChangeStance(Stance.PEACE, friend, true, cs);
            cs.add(See.only(serverPlayer), ChangePriority.CHANGE_LATE,
                new MonarchActionMessage(action,
                    StringTemplate.template(messageId)
                        .addStringTemplate("%nation%", friend.getNationName())));
            break;
        case DECLARE_WAR:
            List<Player> enemies = monarch.collectPotentialEnemies();
            if (enemies.isEmpty()) break;
            Player enemy = Utils.getRandomMember(logger, "Choose enemy",
                enemies, random);
            serverPlayer.csChangeStance(Stance.WAR, enemy, true, cs);
            cs.add(See.only(serverPlayer), ChangePriority.CHANGE_LATE,
                new MonarchActionMessage(action,
                    StringTemplate.template(messageId)
                        .addStringTemplate("%nation%", enemy.getNationName())));
            break;
        case SUPPORT_LAND: case SUPPORT_SEA:
            boolean sea = action == MonarchAction.SUPPORT_SEA;
            List<AbstractUnit> support = monarch.getSupport(random, sea);
            if (support.isEmpty()) break;
            serverPlayer.createUnits(support, serverPlayer.getEurope());
            cs.add(See.only(serverPlayer), serverPlayer.getEurope());
            cs.add(See.only(serverPlayer), ChangePriority.CHANGE_LATE,
                new MonarchActionMessage(action,
                    StringTemplate.template(messageId)
                    .addStringTemplate("%addition%",
                        abstractUnitTemplate(", ", support))));
            break;
        case OFFER_MERCENARIES:
            final List<AbstractUnit> mercenaries
                = monarch.getMercenaries(random);
            if (mercenaries.isEmpty()) break;
            final int mercPrice = serverPlayer.priceMercenaries(mercenaries);
            message = new MonarchActionMessage(MonarchAction.OFFER_MERCENARIES,
                StringTemplate.template("model.monarch.action.OFFER_MERCENARIES")
                    .addAmount("%gold%", mercPrice)
                    .addStringTemplate("%mercenaries%",
                        abstractUnitTemplate(", ", mercenaries)));
            askThisTurn(serverPlayer, message,
                new DOMMessageHandler() {
                    public DOMMessage handle(DOMMessage message) {
                        boolean result
                            = (message instanceof MonarchActionMessage)
                                ? ((MonarchActionMessage)message).getResult()
                                : false;
                        if (result) {
                            ChangeSet cs = new ChangeSet();
                            serverPlayer.csAddMercenaries(mercenaries,
                                                          mercPrice, cs);
                            sendElement(serverPlayer, cs);
                        }
                        return null;
                    }
                }, null);
            break;
        case DISPLEASURE: default:
            logger.warning("Bogus action: " + action);
            break;
        }
    }