Angband's command system
========================

The command system in Angband is one of the two key ways that the game stays separate from the interface that displays it.  The other is the event system, which is currently underutilised.

The idea beyond the command system is that every action the player can perform in-game is encoded as an atomic command sent to the game.  These commands form the basic dialect of Angband.  

Note that the game command system does not cover 'UI actions', such as adjusting the game panel, looking around, and similar.  Targetting can be accomplished by sending a command ("target monster:'small kobold'") but the UI has to do the work to allow that command to be formed (allow the cursor to scroll around the screen, show what monster is currently highlighted, etc. - these things do not fall within the remit of the game core).


The anatomy of a command
------------------------

A command is made up of:
* a command type, e.g. 'eat', 'read'
* a list of arguments, which have a type and a name

Arguments can have any of the following types:
|| null      | no data held
|| string    | a string encoded in UTF-8
|| choice    | an integer indicating a selection from a known set of values
|| item      | a pointer to the struct object describing an item or stack
|| number    | an integer indicating a quantity, power, level, ...
|| direction | one of the 9 directions
|| target    | one of the directions or -1 for a target
|| point     | a struct loc referring to a position in the current level

In C a command is represented by the type 'struct command'.  Command arguments can be set using the cmd_set_arg_*() functions and can be retrieved with the
cmd_get_arg_*() functions.

Limitations:
There can be at most 4 parameters.
The lifetimes for arguments referenced through pointers (i.e. string and item)
has to be at least as long as the lifetime of the command.  The command system
provides little to help control the lifetime of the arguments and to prevent
either dangling references or leaks of dynamically allocated resources.


Command handlers
----------------

Each command type has a command handler function, which takes the command and acts upon it.  A command handler must take the form:

	void command_handler(struct command *);

There is a table, a file-level static named game_cmds in cmd-core.c, that
relates command types to command values.

Inside the command handler, code can access the arguments using the cmd_get_arg_*() functions.  Those will return CMD_OK if there's a parameter matching the name and type provided.  The command handler could also use the cmd_get_{direction,target,item,quantity,string,spell,effect_from_list}() functions which will use the cmd_get_arg_*() functions when the argument is available and will query the user interface for it when it is not.  In the case where the argument was already set or was successfully queried from the user interface, those will return CMD_OK, record the selection made in the command, and pass back the requested value.  In the case where the user interface aborts the selection, those will return CMD_ARG_ABORTED.

If the data type has a validity filter (e.g. cmd_get_item() has both an item type filter and a mode argument to constrain possible item locations) then the getter will ensure that the argument returned satisfies that filter.

For example:

	/* Gain a random spell from the given book (for priests) */
	void do_cmd_study_book(struct command *cmd) {
		struct object *book_obj;

		if (cmd_get_item(
				/* Our command */ cmd,
				/* Name of parameter we're looking for */ "item",
				/* Item to return */ &book_obj,
				/* Prompt */ "Study which book? ",
				/* Error */ "You cannot learn any new spells from the books you have.",
				/* Only allow objects passing this filter */ obj_can_study,
				/* Where are valid choices? */ USE_INVEN | USE_FLOOR) != CMD_OK);
			return;

		/* ... learn from 'item' */
	}




UI handlers
-----------

game-input.h declares a set function pointers (get_string_hook is one) for requesting information from the player.  A UI assigns a specific implementation to a hook (i.e. "get_string_hook = textui_get_string;") to supply its own way of requesting that information.  The hooks that are used by the core of the command system are get_aim_dir_hook, get_effect_from_list_hook, get_item_hook, get_quantity_hook, get_rep_dir_hook, get_spell_hook, get_spell_from_book_hook, and get_string_hook.  The only dispatcher for those hooks which does something potentially useful when no hook is provided is get_effect_from_list():  when get_effect_from_list_hook is NULL it will use a random selection if that is allowed.


Partial list of commands and their arguments
--------------------------------------------

"activate"
Constant: CMD_ACTIVATE
Arguments:
- 'item' (type item): reference to the item to activate

"aim"
Constant: CMD_USE_WAND
Arguments:
- 'item' (type item): the stack of wands to use

"alter"
Constant: CMD_ALTER
Arguments:
- 'direction' (type direction): the direction to alter

"autoinscribe"
Constant: CMD_AUTOINSCRIBE
Arguments:
- none

"autopickup"
Constant: CMD_AUTOPICKUP
Arguments:
- none

"buy"
Constant: CMD_BUY
Arguemnts:
- 'item' (type item): the stack from which to buy
- 'quantity' (type number): the number of items to buy from the stack

"cast"
Constant: CMD_CAST
Arguments:
- 'spell' (type choice): index of the spell to cast
- 'book' (type item): reference to the stack of books to use; only accessed if 'spell' is not set

"close"
Constant: CMD_CLOSE
Arguments:
- 'direction' (type direction): the direction to close

"disarm"
Constant: CMD_DISARM
Arguments:
- 'direction' (type direction): the direction to disarm

"drop"
Constant: CMD_DROP
Arguments:
- 'item' (type item): reference to that stack from which to drop
- 'quantity' (type number): the number of items to drop

"eat"
Constant: CMD_EAT
Arguments:
- 'item' (type item): the stack of food to use

"fire"
Constant: CMD_FIRE
Arguments:
- 'item' (type item): the stack of ammunition to use
- 'target' (type target): the direction or target for the attack

"go down stairs"
Constant: CMD_GO_DOWN
Arguments:
- none

"go up stairs"
Constant: CMD_GO_UP
Arguments:
- none

"hold"
Constant: CMD_HOLD
Arguments:
- none

"inscribe"
Constant: CMD_INSCRIBE
Arguments:
- 'item' (type item): the stack to inscribe
- 'inscription' (type string): the inscription to use

"jump"
Constant: CMD_JUMP
Arguments:
- 'direction' (type direction): the direction to walk

"open"
Constant: CMD_OPEN
Arguments:
- 'direction' (type direction): the direction to open

"pickup"
Constant: CMD_PICKUP
Arguments:
- 'item' (type item): the item to pickup

"quaff"
Constant: CMD_QUAFF
Arguments:
- 'item' (type item): the stack of potions to use

"read"
Constant: CMD_READ_SCROLL
Arguments:
- 'item' (type item): the stack of scrolls to use

"refuel with"
Constant: CMD_REFILL
Arguments:
- 'item' (type item): the stack to use to refuel the currently equipped light

"rest"
Constant: CMD_REST
Arguments:
- 'choice' (type choice): is either the number of turns to rest or one of the special values given by the REST_* constants in player-util.h

"retrieve"
Constant: CMD_RETRIEVE
Arguments:
- 'item' (type item): the stack to retrieve
- 'quantity' (type number): the number of items to retrieve from the stack

"run"
Constant: CMD_RUN
Arguments:
- 'direction' (type direction): the direction to move

"sell"
Constant: CMD_SELL
Arguments:
- 'item' (type item): the stack from which to sell
- 'quantity' (type number): the number of items to sell from the stack

"sleep"
Constant: CMD_SLEEP
Arguments:
- none

"stash"
Constant: CMD_STASH
Arguments:
- 'item' (type item): the stack to stash
- 'quantity' (type number): the number of items from the stack to stash

"steal"
Constant: CMD_STEAL
Arguments:
- 'direction' (type direction): the direction to steal from

"take off"
Constant: CMD_TAKEOFF
Arguments:
- 'item' (type item): reference to the equipped item to remove

"throw"
Constant: CMD_THROW
Arguments:
- 'item' (type item): the stack of items from which to draw one for throwing
- 'target' (type target): the direction or target for the attack

"tunnel"
Constant: CMD_TUNNEL
Arguments:
- 'direction (type direction): the direction to tunnel

"un-inscribe"
Constant: CMD_UNINSCRIBE
Arguments:
- 'item' (type item): the stack to uninscribe

"use"
Constant: CMD_USE_STAFF
Arguments:
- 'item' (type item): the stack of staffs to use

"walk"
Constant: CMD_WALK
- 'direction' (type direction): the direction to move

"walk"
Constant: CMD_PATHFIND
- 'point' (type point): the destination to run to

"wield"
Constant: CMD_WIELD
- 'item' (type item): the stack from which to draw one item
- 'replace' (type item): the ring to replace; only used if 'item' is a ring and all ring slots are filled

"zap"
Constant: CMD_USE_ROD
Arguments:
- 'item' (type item): the stack of rods to use


Design problems to be resolved
------------------------------

Besides the limitations mentioned above for the arguments, the logic for
handling repeated commands is fragile:  various places call cmd_disable_repeat()
or cmd_disable_repeat_floor_item() when they think a change would prevent
repetition of a command.  Some of those are unduly pessimistic (if a stack in the inventory goes away it only would prevent command repetition if that stack was referenced by a command).  Others are not strict enough (https://github.com/angband/angband/issues/5122 is an example of an open issue at the time this was written).  Tnere may be places that should be calling cmd_disable_repeat() which do not.

If commands referred to objects by tval, sval, and location (inventory or floor) that perhaps could help with some of the repetition issues or possibilities for dangling object references.  It could also allow for keymaps to be replaced by commands chains in the text files, since you could then specify "item:inventory:tval=mushroom,sval=Blue" instead of "item:-4", and similarly:

map '2' => { walk(direction: down) }
map 'M' => { cast(spell: "Magic Missile") }
map '^E' => { read(item: "Phase Door") && quaff(item: "Healing") }



Implementation plan
-------------------

DONE:

0a. Move check_state somewhere useful, refactor it so that its data is kept in 3rd normal form.
0b. Move cmd2.c(count_feats + coords_to_dir) => cave.c

1. Clarify split between command and command queue functions (prefixes cmd_ and cmdq_).

2. Refactor get_item() to not use item_tester_hook.

3. Change the argument system

3a. Replace 'cmd_code code, cmd_arg args[]' in command handlers with 'struct command *', remove direct arg access (replace with a halfway house - e.g. cmd_get_arg_item(cmd, 0) )

3b. Slowly switch things across to using the new system, which allows compilation and testing, without breaking things.  This involves relocating the 'fill-in' code from game-cmd.c to the various do_cmd_* functions as well as writing new cmd_get_* functions that check validity of inputs, etc. as above.

3c. Switch from numbered to named arguments.

NOT DONE:

4. Reimplement the following in terms of a core-UI split:

  - ignore

    This is currently almost entirely done in UI.

  - resting

    Instead of having magic numbers and using the 'choice' type, it should take strings (e.g. "*" or "mana" or "hp") or numbers.

  - pickup

    This is currently just a "pickup" command.  It should be separated into a "pick up item x" command and the UI frontend to it. This might be impossible until we get an event-driven game.

  - targetting

    This currently doesn't use the command system at all.


5. Reorganise files:

	{cmd-misc.c + cmd-cave.c(textui_cmd_rest)} -> [ui-misc.c XXX]
	cmd-pickup.c(move_player) -> cmd-cave.c


Later
-----

The get_*() functions in game-input.c have been refactored so they act as dispatchers to the appropriate UI handler.  In some cases (get_quantity(), for instance, which could be implented based on get_string()), it may be desirable to provide a default implementation when the UI does not have one since that could save some code repetition between different UIs.
