@prog pente.muf 1 9999 d 1 i ( If there is an _action: property on trigger @, its value is taken as a command, unless its value is "prefix", which causes the command line up to the first space to be taken as the command. Otherwise, trigger @'s name, up to the first ; [if any], is taken as the command. Games are started by one player offering a game and the other accepting it. The "other" player can also decline the offer, in which case it is discarded; if the "other" player hasn't done either yet, the first player can retract the offer, which also discards it. Any particular pair of players can have at most one game in progress at any one time. Games can be for the record or just for fun. This must be decided no later than the time the offer is accepted. A game for the record has its outcome put into each player's win/loss record and affects ladder standings, whereas a just-for-fun game has no effect on either. Commands and their parameters are as given in the help messages below. Which player gets first move is random the first time two players play; after that, it switches, each game between them. Everything is kept on a single dbref. By default, this dbref is obtained with "trigger @ location" and must be a thing [as opposed to a room or other type of dbref], but if trigger @ has a _holder: property, its value is used instead, regardless of type, as long as either [a] trigger @ has its wizbit set, or [b] the holder dbref has the same owner as trigger @. Players are identified internally by dbref, not name; names are converted to dbrefs, and vice versa, as close to the user interface as possible. In particular, if a player is renamed, everything belonging to that player will automatically carry over to the new name. Offers are stored on the dbref in properties of the form *offer-A-B-: TYPES where A is the offering person, B is the offered-to person, and TYPES is a string containing f if the game could be just for fun or r if it could be for the record. Games-in-progress are stored on the dbref in properties of the form *game-A-B-: STRING where A and B are the players involved [in dbref numbers, A <= B] and STRING is an encoding of the game state. The game state is stored as 21 hex strings, such as are handled by atoq and qtoa, separated by single spaces. The first value gives some game state; the remaining 20 store the board. The game-state value has bitfields thus: The record and turn fields are one bit each. record is 1 if the game is for the record, 0 if it's just for fun; turn is 0 if it's A's turn, 1 if B's turn. The capture count fields are four bits each. Thus, for example, if that number is ca, or 1100010010 in binary, then the game is for the record, it's B's turn, A has captured one pair, and B has captured two pairs. Who-moves-first state between two players A and B is stored in a property *turn-A-B-: BIT where BIT is 1 if A should move first and 2 if B should, next time those two players start a game between them. [Modifications to this property are locked by the game lock.] As for *game- props, A <= B. A player's default-game setting [the "game" command] is kept in a *def-: property, whose value is the default game. If there is no default game, the property can be present with a zero-length value or absent. The 20 strings that store the board are simply the board rows, represented as numbers in base 3 and converted to hex. An empty cell is represented as 0, a piece belonging to A as 1, and a piece belonging to B as 2. For example, if the board row looks like - - A - B A B B B A - - - - A - - - - B then the base-3 number will be 0 0 1 0 2 1 2 2 2 1 0 0 0 0 1 0 0 0 0 2 which is 167286062 decimal, or 9f8952e as it would appear in the property [ie, in hex]. Rows higher on the board appear earlier in the property. Settings [see the "set" command] are kept in a *set-: property, which contains one character per setting that differs from the default: "set" keyword character move m show s watch w autoshow a If all the defaults are in effect, the property may be absent or may be present with a zero-length value. There is a lock that prevents offers from being made, retracted, accepted, or declined [except, of course, by the holder of the lock]; this lock takes the form of a property *lock-offers: [for example: *lock-offers: 1234 909524337]. A similar lock *lock-games: prevents games from being started or finished while it is set. Locks older than ) $def lock-timeout-time 60 ( seconds are considered stale and are ignored. The code is careful to never block while it holds a lock. Individual games are not locked; only the player whose turn it is may modify a game-in-progress, so no locking is necessary. When waiting for a lock, the first ) $def lock-yield-count 3 ( failures provoke simple "yield" calls; after that, one-second sleeps are done instead [with timed-prompt, so that the player can break out]. After ) $def lock-warn-count 6 ( failures, a warning is printed. After that, nothing is done until either the lock is obtained [possibly due to an existing lock going stale] or the user aborts the wait. Whenever a given piece of code needs to have both offers and games locked, it must always lock offers first [but it may unlock in either order]. ) $def conf-size 3 (size of border printed for move confirmation) : help-info- "Commands are as follows. Use \"help \" for help on ," "as in \"help offer\" for help on the \"offer\" command." " " "rules - print game rules" "move - make a move in a game" "show - show the current state of a game" "check - check if you have anything to do" "offer - offer to play a game with someone" "retract - retract an offer you made" "accept - accept an offer made to you" "decline - decline an offer made to you" "ladder - show the game ladder" "help - (also \"?\") show help info" "games - list all games you have in progress" "offers - list all outstanding offers involving you" "record - show someone's win/loss record" "game - pick a default opponent for move and show commands" "resign - give up a game" "set - set various options" "toadsweep - clean up after toaded players" me @ prog owner dbcmp if "cmdstats - show command statistics" then ; : help-info-rules "rules []" " Prints game rules. With no argument, prints a table-of-contents list;" " with an argument, prints that page from the rules." ; : help-info-help "help []" " Prints help information. If no command is given, prints a list of" " commands, with a short description of each one. If a command is given," " prints help info for that command." ; : help-info-offer "offer [{fun|record}]" " Extend an offer to another player, whose name must be given. The" " optional argument says whether the game is just for fun or is for the" " record; if it is not specified, the other player may choose when" " accepting the offer. If you already have an offer extended to that" " player, it is replaced." ; : help-info-retract "retract " " Retracts your offer of a game to the specified player. If you have no" " offer currently extended to that player, a message saying so is printed" " and nothing is done." ; : help-info-decline "decline " " Declines an offer the specified player has made to you. If there is no" " such offer outstanding, a message saying so is printed and nothing is" " done." ; : help-info-offers "offers" " Lists all offers that have been made to you or that you have made, but" " which have been neither accepted, declined, nor retracted." ; : help-info-set "set