1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268
|
@c tyrant.texi - Texinfo about Tyrant mode, and all the games -*-texinfo-*-
@c
@c $Id: tyrant.texi,v 1.3 1999/11/29 20:32:36 zappo Exp $
@c
@c Copyright (C) 1997, 1999 Free Software Foundation
@c
@node Tyrant Mode, Log Buffer, Advanced Features, Top
@chapter Tyrant Mode
@cindex tyrant mode
Analogically, tyrant-mode is a minor-mode used for taking over innocent
major modes. Tyrant mode will usually be seen under the controlled use
of emacs talk for the playing of games against other network bound
users. It works by rebinding the keyboard, and referencing all
keystrokes to the game's local keymap. Valid keystrokes are then sent
over the network, and simultaneously executed locally. When keystrokes
are received from a network connection, the command that key is bound to
is then executed. Thus, two independant emacses can play the same game
together.
To initiate a game, one must have an open connection to someone using
emacs talk. Then the keystroke @kbd{C-c g} will prompt you for the game
you wish to play.
Once a game is selected, the remote is queried to play that game against
you. If they choose yes, then that game is automatically started.
It also possible to start up a select few games to play against the
computer. To do this, use the command @code{tyrant-play-computer} which
uses tyrant mode to play against some function written in lisp (which can
do whatever it wants to make decisions.) Tyrant-ai has the same
controls as tyrant mode under etalk.
@menu
* Playing a Game:: General game features, and specific rules.
* Installing Games:: How to install and configure all the games.
* Writing Games:: How to write a game to use under tyrant mode.
@end menu
@node Playing a Game, Installing Games, Tyrant Mode, Tyrant Mode
@section Playing Tyrant mode games
@cindex tyrant-mode games
Once a game has been started, there are some standard commands
available, which are:
@table @kbd
@item C-c C-c or C-x k
Cancel this game. Doing so asks both sides to hit return, which
restores the original talk windows. The reason @kbd{C-x k} is also
listed is because killing the buffer would terminate the connection, not
cancel the game.
@item C-h
Tyranted game mode help. This will offer some help for tyrant mode, or
the game in question. @kbd{C-h} twice will do a @code{display-mode}.
@item C-c m
Send a message to the opponent in the minibuffer. This allows some
communication during the game.
@end table
For the impatient, most games have the following key bindings for
consistency:
@table @kbd
@item C-f
Move forward (left)
@item C-b
Move backwards (right)
@item C-p
Move previous (up)
@item C-n
Move next (down)
@item SPC
Do something (grab, move, etc)
@item P, g
Pass/Go (if applicable in the games context)
@end table
For these keys, when possible, the arrow keys (vt100 under 18, and all
emacs 19 terminals supported) will be mapped to the correct direction,
and converted into the sequence @kbd{C-f}, @kbd{C-b}, @kbd{C-p} or
@kbd{C-n} so the remote can interpolate it. @refill
Also, in many games, there is mouse support under emacs 19. In general
a @code{click} event moves the mouse to the clicked on square, and does
the same thing @kbd{SPC} would. @code{mouse-movement} and @code{drag}
events simply move the cursor about within the confines of the board.
@refill
The only caution is with mouse movement events. When playing over the
network, you can seriously overload the net and the parsing ability of
the remote, and pull the two boards out of sync. I strongly suggest you
drag slowly when using tyrant mode, or just skip it and only use 'clicks
to do what you want.
Because mouse commands are converted into tyrant control messages, mouse
commands will be allowed when the other user is not using an X display.
Lastly, when playing over the network, tyrant-mode will keep track of
the current turn, and your keystrokes will only be valid if it is
currently your turn. You can tell when it is your turn because the
string ``T-Con'' appears in the list of minor modes, meaning the console
is in your terminal.
The etalk distribution comes with the following games, and it is very
easy to add or write new games.
@menu
* Talk Tac Toe:: Simplistic tic-tac-toe game
* Hangman:: Hangman! Player one makes up a word, player2 guesses.
* Drop 4:: Drop pieces to get 4 in a row.
* 4 by 4:: A drop 4 derivative that is even more challenging.
* Word-Thing:: Make words from tiles, and place them on a board.
* Dots:: DOTS! Not just for paper anymore.
* Reversi:: An othello like game where you battle for stones.
* Chinese Checkers::That weird marble game.
* Order and Chaos:: A weird game of pure Offense/Defense for Order/Chaos
* Ataxx:: That funny blob game.
* Checkers:: Checkers.
* Gess:: Gess game (Go chESS) as seen in Scientific American.
* Trax:: That nifty tile game from New Zealand.
* Chess:: Chess.
* Bomb:: A game of explosions!
@end menu
@node Talk Tac Toe, Hangman, Playing a Game, Playing a Game
@subsection Playing talk-tac-toe
@cindex talk-tac-toe
@dfn{Talk-tac-toe} does not require the use of tyrant mode and can be run
without it. It makes a buffer with a simple tic tac toe board in it.
To play, just hit a number and your move is recorded in the
appropriate square. When it isn't your move, the tyrant will tell you
so.
@node Hangman, Drop 4, Talk Tac Toe, Playing a Game
@subsection Playing hangman
@cindex Hangman
Hangman does require talk to be running. It too is simple. The
initiator is required to type in an initiation string. This string has
to be < 30 characters, and all upper case letters and symbols are not
turned into @dfn{_} characters.
The initiator then watches, and can send messages @kbd{C-c m} while player
two hits letters until he gets the word, or runs out of body parts.
It's fun. Trust me. :)
@node Drop 4, 4 by 4, Hangman, Playing a Game
@subsection drop 4
@cindex drop4
Drop 4 is a tic tac toe like game. Your pieces start at the top of the
screen, and hitting SPC drops that piece. The purpose is to get 4 in a
row. The pieces are:
@example
Player 1 /##\ Player 2 /--\
\##/ \__/
@end example
@noindent
Keys:
@table @kbd
@item 0-9
Select that numbered column.
@item f, C-f, .
Move the piece to the left.
@item b, C-b, ,
Move the piece to the right. (note. @kbd{,} and @kbd{.} are
just under the @kbd{<} and @kbd{>} on most keyboards.)
@item RET, SPC
Drop piece.
@item q
quit.
@item mouse
Drags move the piece left and right. A click drops.
@end table
This game is very addicting, so be careful.
@node 4 by 4, Word-Thing, Drop 4, Playing a Game
@subsection 4 by 4
@cindex 4 by 4
4 by 4 is a game of my own invention. It can be played with, or without
tyrant mode running.
It is based on an 8x8 board, and the purpose is to get 4 pieces in a
row. Like drop 4, pieces always start on one side of the board.
Unlike Drop 4, that side can be any of the 4 walls. (Thus, 4X4)
The player pieces are ``##'' for player 1, and ``::'' for player 2.
The movement keys are the typical emacs movement keys, @kbd{C-f},
@kbd{C-b}, @kbd{C-n}, @kbd{C-p} and their non-control versions @kbd{SPC}
will attempt to place a peice. The strategies for playing are very
similar to that of drop 4, with the extra elements of the additional
building blocks. Mouse drag actions will move the selected square, and
a click places a piece.
This game has similar addicting properties as Drop 4.
@node Word-Thing, Dots, 4 by 4, Playing a Game
@subsection Word-Thing
@cindex word-thing
Word-Thing works for both tyrant mode, and by itself. The concept of
the game is the same as the popular Scrabble game except that many rules
are changed.
The idea is to take your tiles, (in the ``WORD-THING COMMAND'' window)
build a word, and move the outline of that word in the ``WORD-THING
BOARD'' window. All key presses take place in the ``WORD-THING COMMAND''
window.
A typical hand may look like this:
@example
+---+ . . . +---+ +---+ +---+ +---+ +---+ +---+ +---+
| | . . | | | | | | |eow| | | | | | |
| T | . R . | A | | I | | N | | | | W | | M | | E |
| | . . | | | | | | | | | | | | | |
+---+ . . . +---+ +---+ +---+ +---+ +---+ +---+ +---+
Word is now -> TAIN WME <-Score Them [9] You [0]
@end example
Where the tile surrounded by periods ( . . . ) is already on the board,
and the tile with @code{eow} in it marks the @dfn{end-of-word}. The
score is then placed in the following line. This hand will place the
word ``TRAIN'' on the board over a word that has an ``R'' in it.
When it isn't your turn, the letters in the tiles are replaced with the
@kbd{?} character, and the letters to your hand are placed where the
``word is now'' points to, so that you may contemplate possible moves.
The currently ``selected'' tile is the one with the cursor on it.
Tile movement is based on the selected tile.
The command keys are as follows.
@table @kbd
@item ,
Select tile to your left.
@item .
Select tile to your right.
@item <
Move selected tile to the left.
@item >
Move the selected tile to the right.
@end table
The choice of some of these keys are based on the configurations of PC
and DEC post VT420 keyboards which have the following keys next to each
other.
@example
+-----+ +-----+
| < | | > |
| | | |
| , | | . |
+-----+ +-----+
@end example
Thus, moving a tile is simply a difference of holding down a shift key.
Other important keys are:
@table @kbd
@item C-f, f
Move word marker left on board.
@item C-b, b
Move word marker right.
@item C-n, n
Move word marker down.
@item C-p, p
Move word marker up.
@item t
Turn the word between horizontal and vertical.
@item RET
Place the word at this location.
@item g
Give up your turn if you have a REALLY bad hand.
@item G
Give up your turn, and get some new tiles if your hand is worse than that.
@end table
The following rules hold when playing this version of word-thing.
@enumerate
@item
There must be at least 1 three letter word in a placement.
@item
A word must either overlap the @kbd{*} piece, or another word.
@item
All new or changed words are scored together, including duplicated
letters only if the duplicated letter is one you place down.
@item
Valid words are those passed by the unix spell checker or by ispell,
except for two letter words which must be in an alist in the word-thing
source.
@item
There are no bonus squares since they made the words unreadable on the
screen.
@end enumerate
This game will only work if the initiator has spell or ispell installed.
@node Dots, Reversi , Word-Thing, Playing a Game
@subsection Dots
@cindex dots
Dots is an old game. The board is made of lots of dots (hence it's
name) and in emacs' case, plus signs. A move is to place a line between
two points, either vertically or horizontally. The goal is to capture a
box. A box being when you make 4 lines around a center. At this point,
you have captured a box. The person with the most boxes is the winner.
The keys are the typical emacs movement keys [C-]f,b,n,p with optional
control being held down. SPC will place a line. Mouse actions will
select a line, and a click will put a line down.
When you capture a box, turns are not swapped, your name is placed in
the box, and you may move again.
@node Reversi, Chinese Checkers, Dots, Playing a Game
@subsection Reversi
@cindex Reversi
Reversi is like Othello. A legal move is one where the new piece and an
old piece surround the opponent linearly. Upon placing a piece, all of
the opponents pieces between the new piece and all old pieces are
scarfed up. To win, get as many pieces as you can.
Movement is done with the arrows, and SPC tries to place a piece. Mouse
actions select, or place peices.
@subsection Toreversi
@cindex Toreversi
Toreversi is identical to Reversi with one rather interesting exception.
There are no edges. The board is folded into a torus, or donut shape,
so a move may capture stones over one edge, in any direction, onto the
other side of the board. This causes many interesting occurances to the
novice, and removes the great importance placed on the edges of the
board.
Movement is identical to that of Reversi.
@node Chinese Checkers, Order and Chaos ,Reversi, Playing a Game
@subsection Chinese Checkers
@cindex Chinese Checkers
Chinese checkers is a game where both players move all their pieces to
opposite sides of the board. In this ``O'' is player 1, and ``X'' is
player 2. Movement can consist of one piece either moving to one
adjacent square, or to jump, one piece at a time, as many as they can.
Movement is done with ``Empire'' keys. Mainly, a map where:
@table @kbd
@item y
Goes up and left.
@item u
Goes up and right.
@item g
Goes left.
@item j
Goes right.
@item b
Goes down and left.
@item n
Goes down and right.
@item SPC, h
Point. Either grab or drop.
@end table
To make a move, put the cursor on a piece, and hit @kbd{SPC}. This
marks it. Then use movement keys to make it go. Going to an adjacent
square unmarks and changes turns. Jumping requires that you hit
@kbd{SPC} a second time to drop it. Once jumping has commenced, moving
to an adjacent square at the end is illegal.
There is no mouse support yet.
@node Order and Chaos, Ataxx, Chinese Checkers, Playing a Game
@subsection Order and Chaos
@cindex Order and Chaos
Order and Chaos is a weird game someone asked me to write. The rules
are that ORDER tries to get 5 in a row of either type (X or O pieces)
Chaos tries to prevent him from doing that. Both players can place a
piece of any type on the board.
Movement is done with the standard emacs movement keys. An @kbd{x}
places and X piece, and an @kbd{o} places and O piece.
Mouse drags will move the selected square. A click with mouse button 1
will place an X piece, and a click with button 2 will place an O piece.
@node Ataxx, Checkers, Order and Chaos, Playing a Game
@subsection Ataxx
@cindex Ataxx
Ataxx is a game where the winner is the person with the most pieces when
the board is full. Play is done by moving the cursor, grabbing a
target. Then move the cursor to a new location, and place it there.
A move to an adjacent piece will make a new piece in that location, and
take all of your opponents pieces neighboring it.
A move 2 away will jump that piece into that location, and grab all
of your opponents pieces adjacent to it.
Movement is done with the standard emacs movement keys.
@kbd{SPC} will grab a piece you own.
@kbd{SPC} will drop that piece after it has been grabbed.
@kbd{P} will allow you to give up your turn.
Mouse drags will move the selected square, and a click will GRAB or DROP
a piece somewhere.
@node Checkers, Gess, Ataxx, Playing a Game
@subsection Checkers
@cindex checkers
The rules for checkers:
@enumerate
@item
A piece may move forward any one diagonal square.
@item
A piece may jump forward diagonally and capture over any opponent's piece.
@item
A piece reaching the far side of the board is kinged.
@item
A king may move forwards or backwards to an adjacent diagonal.
@item
A king may jump in any diagonal over an opponent and capture them.
@item
A king may jump over his own men without penalty.
@item
Several jumps are allowed.
@end enumerate
To play, use the arrow keys to select a piece. Then use @kbd{SPC} to
mark. Move the cursor to where you want to place the piece and hit
@kbd{SPC} a second time to go there. To release a piece, and grab a
different piece if you haven't jumped anyone, place the cursor on the
grabbed piece and hit @kbd{SPC}.
Mouse drags move the selected square. A click will GRAB or MOVE a
checker.
@node Gess, Trax, Checkers, Playing a Game
@subsection Gess, and Gess alternate footprint
@cindex Gess, Gess-alt
Gess is a game similar to chess, but played on a Go board. For more
information check the Scientific American article on November 1994.
A "piece" is any group of up to 9 stones in a 3x3 block. Movement is
based on the position of stones. Pieces on the outer edge of the square
show how movement is allowed. If the center is filled, then movement is
infinite in any direction. When empty, movement is limited to up to 3
spaces in any given direction. On an X display where faces are
available, the viable moves are highlighted for convenience.
The following examples Describe movement.
@example
... This piece represents a "pawn". It can move down 3 spaces.
...
.X.
.X. This piece represents a "Rook". It can move up, down, left,
XXX and right as far as it wants.
.X.
X.X This piece represents a "Bishop". It can move in any diagonal
.X. as far as it wants.
X.X
XXX This is your ring, or "King". It can move in any direction,
X.X but can only do so up to 3 dots away at a time.
XXX
XXX This is a tee, or a mutant piece created by pushing the initial
.X. rook up next to it's pawn. It is my experience that this is
.X. a handy configuration.
.XX This is a mutant piece. It can move up the 3 spaces up, diagonal
... up-right, and down.
.X.
@end example
As with chess, you can "capture" the opponants stones. When moving, you
may move up to your maximum distance which is usually stoped by a wall,
or someones pieces. You may only overlap the opponant or yourself by 1
series of stones. If you are moving as a rook, the most stones you may
take are 3. If moving as a bishop, the most stones you can capture is
5. You may also capture your own stones, but this is not very useful.
In Gess, you overlap when the "footprint" lands on any other stone. In
normal Gess this footprint is the entire 3x3 block. With the alternate
footprint rule, the footprint only consists of stones in the active
piece.
A piece becomes invalid in normal gess when an opponant's stone is
somewhere in your designated 3x3 block. This is not true with the
alternate footprint version.
The goal is to break your opponants ring (King). In the course of play,
it is possible to also make a new ring. Emacs will keep track of your
original ring for speed, and when it is broken, it will look for new
rings to take it's place.
To play, use the arrow keys to move about. Use @kbd{SPC} to select a 3x3
block. If you are using X with faces available, the possible places to
move are highlighted. Move the cursor to a new CENTER for your block.
Press @kbd{SPC} to move your piece.
With a mouse under X, click to select a 3x3 block to be your piece, and
click on a new valid spot to go there.
@node Trax, Chess, Gess, Playing a Game
@subsection Trax
@cindex Trax
Trax is a tile based game, where there are basically 2 types of tiles.
The two tiles are a "Cross" and two "Curves". When playing real trax,
the tiles have black and white player lines on them. In emacs, they
look more like this:
@example
+..#..+ +..#..+
: # : : # :
------- and ## /--
: # : : / :
+..#..+ +..|..+
@end example
The goal is to create a "loop" of your color. The other winning
strategy is to create a line that covers eight or more tiles from two
parallel edges. The line must cover the maximum extent of the board,
not the eight tile minimum.
A sample game with a win loop in it may look like this:
@example
1 2 3 4 5
A
. . .
+..|..+..#..+..#..+
B : | : # : # :
. ###|#### /---\ ## .
: | : / : \ :
+..|..+..|..+..|..+
C : / : | : \ :
. --/ ####|#### \-- .
: # : | : # :
+..#..+..|..+..#..+
D : # : | : # :
. --\ ####|#### /-- .
: \ : | : / :
+..|..+..|..+..|..+
. . .
@end example
Here we see the "." tiles which are places where we can place tiles
legally, and there is the big loop of "###" marks. This loop signifies
a win for player 2.
Player 1 is represented by the "---" lines, and player 2 is represented
by the "####" marks.
To play, use the normal movement keys to put the cursor on a space with
a "." in the center. Next, press @kbd{SPC} to select a tile to put
there. Only the center of the tile is drawn. Continue to press
@kbd{SPC} until the piece you want is under the cursor, then hit
@kbd{RET} to drop it there and switch turns. A move may place multiple
pieces on the board at once. These other pieces are called "forced
moves" and are handled by emacs. Forced moves are usually the winning
factor when playing trax.
There is no mouse support.
@node Chess, Bomb, Trax, Playing a Game
@subsection Chess
@cindex Chess
Chess is chess. Movement is handled by the @kbd{[C-] f, b, n ,p} keys,
and the mouse can be used to move around as well. To select a piece to
be moved, hit @kbd{SPC} on it, or click with the mouse. That piece will
be marked with @samp{> <} characters. Every valid location you can move
to will be marked with @samp{( )} characters. To move, simply click
there with the mouse, or move with the cursor and hit @kbd{SPC} again.
If there is a special type of move, like a "castle" then some position
related to the move (Such as the rook in a Castle) is marked with
@samp{! !} characters. Selecting that space performs the special move.
To drop a piece, and select another, select the piece a second time and
all marks will go away.
Each time a select of some type is done, an extra buffer is updated. It
contains lost pieces, and the most recent action taken.
To win, capture the other guys king.
The chess game code has been organized in order to make it easier to
create "Chess Variants". If you have a favorite chess variant, it may
be possible to easilly create it by using most of the chess code as it
currently stands.
@node Bomb, , Chess, Playing a Game
@subsection Bomb
@cindex Bomb
Bombs is a fun game played on a board which happens to be 6x5 in this
implementation. Movement is handled with @kbd{[C-] f, b, n ,p} keys or
by clicking with the mouse.
Each move consists of dropping a "bomb". Player 1 bombs are @samp{@@}
symbols, and player 2 bombs are @samp{*} symbols. You may place a bomb
into an empty square, or into a square where you already have a bomb.
Every square has a maximum volume. This volume is defined by the number
of adjacent squares available. Thus a corner has a volume of 2, an edge
has a volume of 3, and a central square has a volume of 4. When there
are enough bombs in a square to fill that volume, that square explodes.
When a square explodes, it will briefly flash, and one bomb will land in
each adjacent square. If your opponant is in that square, you take it
over. If that square reaches it's volume, it explodes as well.
You win if you explode over all your opponant's squares.
For instance, the corner situation for @@s move in the upper left
(where the ! is) would work like this:
@example
------->
+-----+-----+-- +-----+-----+--
| ! | | | | |
| @@ | * | | | @@ @@ |
+-----+-----+-- +-----+-----+--
| | * | | | * |
| @@ | * * | | @@ @@ | * * |
+-----+-----+-- +-----+-----+--
| | | | | |
| @@ | | | @@ | |
@end example
Now, it's * turn. When this happens, we will see a chain reaction,
during which, * will win.
@example
-------> ------> ----->
+-----+-----+-- +-----+-----+-- +-----+-----+-- +-----+-----+--
| | | | | * | | | | | | |
| | @@ @@ | | | * * | | * * | | * | | * | *
+-----+-----+-- +-----+-----+-- +-----+-----+-- +-----+-----+--
| | *! | | * | | | | | | | |
| @@ @@ | * * | | * * | | * | | * * | * | * | * * | *
+-----+-----+-- +-----+-----+-- +-----+-----+-- +-----+-----+--
| | | | | | | | | | | |
| @@ | | | @@ | * | | * * | * | | * * | * |
@end example
@node Installing Games, Writing Games, Playing a Game, Tyrant Mode
@section Installing games
@cindex installing games
If a new game is written, and you wish to install it, it can simply be
placed in the @file{games} directory wherever etalk is installed. If
you do not have permission to this directory, you may create a
@file{games} directory under your personal lisp library, and place the
new game there. The games list is built by searching @code{load-path}
for all lisp files in a @file{games} subdirectory.
Whoever you are talking to, however, must also have this game installed
to be able to play against them.
@vindex game-lib-use-colors
The only tyrant configuration variable is @code{game-lib-use-colors},
which enables the use of faces in games when set. If you use emacs 18,
then this will just be ignored.
The colors used in games can be controlled through X resources. Valid
attributes you can set are:
@table @code
@item emacs*game-lib-player1-face
@item emacs*game-lib-player2-face
@end table
As with all faces, use .attributeForeground, and .attributeBackground to
change the colors.
@node Writing Games, ,Installing Games, Tyrant Mode
@chapter Writing Games
@cindex Writing Games
To write a game, there is a basic structure that must be adhered to.
This is, however, easy to do since much of it is handled by the
@file{game-lib.el} routines.
There are several features of tyrant-mode which you may wish to be
familiar with to improve the games you write as well. As an example, we
will examine the first game I wrote, which is talk-tac-toe, and how it
is constructed, and uses the hooks and features of tyrant-mode with
game-lib.
All tyrant-mode style games can be written and tested without ever
entering etalk until the interaction with tyrant-mode is actually
tested.
@menu
* Initialization :: How to initialize for using tyrant-mode
* Using Faces :: How to use colors in your games
* Swapping Turns :: How to swap turns
* Winning :: How to declare a winner
* Mouse Control :: How to use the mouse under tyrant-mode
* Secret Messages :: Passing secret messages between etalk clients
* Asking Questions :: How to ask a question in a minibuffer
* Gamelib functions :: Listing of functions for game-lib and tyrant-mode
@end menu
@node Initialization, Using Faces, Writing Games, Writing Games
@section Initialization
@cindex Initializing Tyrant mode (code)
The first thing you must do is determine the name you wish to use. The
file name, and the name of the entry point of your game-mode must be the
same, and *MUST NOT* end in -ai, or -lib. (Such as game-lib.el) since
those file names are all filtered out of the games directories when the
list of games is generated.
Next, lets look at some sections from the main entry point of talk-tac-toe:
@example
(defvar ttt-map nil
"Keymap used in talk-tac-toe.")
(if ttt-map
()
(setq ttt-map (make-sparse-keymap))
(define-key ttt-map "q" 'ttt-quit)
[ ... ]
(game-lib-add-mouse-support ttt-map)
)
@end example
Here we see the creation of the keymap. The keymap should always be
sparse. It may make playing singly unpleasant at times, but it will
improve the tyrant's control.
The last function call, @code{game-lib-add-mouse-support}, is a function
which takes the keymap of your choice, and adds mouse support to it. It
handles problems when dealing with emacs18, and other unpleasantries.
@findex game-lib-add-mouse-support
@example
(interactive)
(let ((buff (get-buffer-create "TALK-TAC-TOE")))
;; bring buffer forwards
(switch-to-buffer buff))
(setq major-mode 'talk-tac-toe)
(setq mode-name "T-T-T")
(use-local-map ttt-map)
;; toast buffer contents
(game-lib-clear-buffer)
;; insert board into buffer Note: spaces etc have been counted so
;; keeping this clean is importnat.
(game-lib-insert-string 1 "-------------
| 1 | 2 | 3 |
-------------
| 4 | 5 | 6 |
-------------
| 7 | 8 | 9 |
-------------" nil)
@end example
Here we see two important things.
@enumerate
@item
Creation of a buffer, and selecting that buffer as current. It must be
current when tyrant-mode checks to see what happened, and begins to take
over your game buffer.
@item
Clearing of the buffer with game-lib. This clears out the buffer,
overlays, and some other nice things.
@item
Creation of the game board with @code{game-lib-insert-string}. This
function should be used when inserting strings if you plan on using any
overlays of any sort. @xref{Using Faces}.
@end enumerate
Next, some variables are created.
@example
(make-local-variable 'tyrant-turn)
(setq tyrant-turn 1)
;; tyrant mode mouse support
(make-local-variable 'tyrant-mouse-function)
(setq tyrant-mouse-function 'ttt-mouse-support)
;; tyrant mode help string
(make-local-variable 'etalk-tyrant-brief-help)
(setq etalk-tyrant-brief-help
"TalkTacToe: # to move, q to quit, C-c m to send message.")
(make-local-variable 'etalk-tyrant-quit-string)
(setq etalk-tyrant-quit-string "")
;; ok.. setup hooks dependent on whether you are player1 or player2
(setq tyrant-player1-hook
'(lambda ()
(message "You are player 1")))
(setq tyrant-player2-hook
'(lambda ()
(setq etalk-tyrant-enabled-console nil)
(message "Your are player 2"))) ;player2 goes 2nd
)
@end example
Much of this is explained in the comments. Briefly again, these
variables are mostly control features of tyrant mode. They are:
@table @code
@item tyrant-turn
This important variable controls whose turn it is. So long as you use
this, and it's value is always 1, or 2, game lib features discussed
below shall always work efficiently.
@item tyrant-mouse-function
This variable will hold a symbol to your function which can control how
the mouse is handled. This function's parameters are described later.
@item etalk-tyrant-brief-help
This variable is simply a string printed when the user presses @kbd{C-h}
under tyrant-mode.
@item etalk-tyrant-quit-string
This variable can be either @code{fset} to a function which can generate
message saying who wins, or a generic string declaring the winner. Here
we see that no extra text will be printed. If a winner is declared
(see below) then this feature is not used. If you can declare a winner
half way through the game, then @code{fset} this to a function which returns a
string saying who that player is. (See DOTS, and REVERSI for examples)
@item tyrant-player1-hook, tyrant-player2-hook
These two hooks are your only entry way into knowing under tyrant-mode
which player you are running as. Here we simply print out which player
we are running as. Notice that we set the console to be disabled for
player two. This is because it is not his turn. This variable must be
set or both players can mess with the board at the same time.
@end table
@node Using Faces, Swapping Turns, Initialization, Writing Games
@section Using Faces
@cindex game-lib faces
There are several default faces generated by game lib. They are:
@table @asis
@item game-lib-player1-face
@item game-lib-player1-face-R
@item game-lib-player2-face
@item game-lib-player2-face-R
@end table
The are used in most games where color doesn't matter. If you have no
preference to the color of your pieces, these should be fine. If you
would like additional colors to represent other things, you can use the
function @code{game-lib-load-color} to create new ones.
@defun (game-lib-load-color FACE L-FG L-BG D-FG D-BG BOLD)
This function will create FACE, and based on the background color of the
current fram, choose either L-FG/BG or D-BG/FG colors. A nil mean to
use the default color of the frame. If BOLD is non-nil, then boldify
the face.
@end defun
To insert text and give it a certain face, use the function
@code{game-lib-insert-string}. It automatically inserts the string,
defaulting to overwrite mode unless @code{game-lib-replace} is
@code{nil}.
@defun (game-lib-insert POINT STRING FACE)
At POINT, insert STRING. If the variable @code{game-lib-replace} is @code{t},
then replace the text under the cursor, extending a line if necessary.
If @code{game-lib-replace} is @code{nil}, then insert the text.
When replacing text, any overlays currently covering the same area are
removed, and an overlay consisting of FACE is place there in it's stead.
@end defun
@node Swapping Turns, Winning, Using Faces, Writing Games
@section Swapping turns
@cindex Swapping turns in tyrant-mode (code)
Exchanging turns under tyrant-mode is quite simple. Here is an example
from talk-tac-toe:
@example
(defun ttt-swap-turns ()
"Go to next person's turn."
(game-lib-swap-turns "It is now %P's turn." "Player %d's turn"))
@end example
@defun (game-lib-swap-turns ETALK-MESSAGE SOLO-MESSAGE)
This should be all you need. ETALK-MESSAGE is printed when running in
etalk mode. Codes as defined by @code{tyrant-format} @xref{Gamelib
functions}, is used for formatting. If running both players from one
terminal, the SOLO-MESSAGE is used, replacing one %d with the player
index of the new turn.
@end defun
The net result of calling this function is the change the value of
@code{tyrant-turn} to be the next person's turn, and then the set the
tyrant-console to the appropriate player.
@node Winning, Mouse Control, Swapping Turns, Writing Games
@section Winning
To declare a winner, and subsequently exit the game buffer and return to
the talk buffers, the following example from talk-tac-toe is all you
need.
@example
(if (setq didiwin (ttt-detect-win))
(game-lib-win tyrant-turn "%P wins!" "Player %d wins!")
(if (equal ttt-numb-moves 9)
(game-lib-win tyrant-turn "No moves left! Stalemate."
"No moves left! Stalemate.")))
@end example
@defun (game-lib-win WINNER ETALK-MSG SOLO-MSG)
Like @code{game-lib-swap-turns} it takes two parameters for the string
to print. ETALK-MSG says who wins based on @code{tyrant-format}, and
SOLO-MSG for when played alone. WINNER is the winner in question. This
value is used to determine the name to print. As you can see, it can
also be used to declare a stalemate.
@end defun
Another way to determine a winner is by @code{fset}ing the variable
@code{etalk-tyrant-quit-string} to some function. Doing this will let
you declare a winner in the middle of a game if someone gives up.
Here is an example from @code{word-thing} which can declare a winner
before all the tiles are used up.
@example
(defun word-thing-win-string ()
"tyrant only function, generates a string declaring someone the winner"
(save-excursion
(set-buffer word-thing-command-name)
(if (> word-thing-player-1-score word-thing-player-2-score)
(tyrant-format "%n is the winner!")
(tyrant-format "%N is the winner!"))))
@end example
Here, simply do whatever is necessary to return a string usable by
@code{tyrant-format} to say who won. Notice that %n, and %N is
different. @xref{Gamelib functions}.
You may also kill the game at any time. Here is an example of a
specific quit function from talk-tac-toe:
@example
(defun ttt-quit ()
"Quit talk-tac-toe nicely"
(interactive)
(game-lib-quit t))
@end example
@defun (game-lib-quit KILL)
Here, @code{game-lib-quit} is called with "t". The t is in the "kill"
field which simple tells game-lib to kill the talk buffer when it is
done with it, which minimized cleanup later on.
@end defun
@node Mouse Control, Secret Messages, Winning, Writing Games
@section Mouse Control
@cindex tyrant mouse control
Using the mouse under tyrant-mode has been simplified through the use of
the key-binding @code{game-lib-add-mouse-support} @xref{Initialization}.
The function assigned to the variable @code{tyrant-mouse-function} can
be anything devised for use by your game program. Once installed, this
feature is usable during solo play, and against an opponent in tyrant
mode.
Here is a sample from talk-tac-toe:
@example
(defun ttt-mouse-support (p e m)
"Reads in a mouse event from the game-lib driver, and allows a
player to click on a square."
;; find which square we are closest to and go there
(if (and (not (memq 'drag m)) (integerp p))
(let ((first-line 0)
(line-width 14)
(block-width 3)
(block-height 1)
(block-vsep 1) ;vertical separator width
(block-hsep 1) ;horizontal sep width
x y xt yt
)
(setq yt (/ (- p (* first-line line-width)) line-width))
(setq xt (- (% p line-width) 1))
(setq y (/ yt (+ block-height block-vsep)))
(setq x (/ xt (+ block-width block-hsep)))
(message "Clicked on %d %d" x y)
(if (not (or (< (% xt (+ block-width block-hsep)) block-hsep)
(< (% yt (+ block-height block-vsep))
block-vsep)))
(if (memq 'click m)
(let ((last-input-char (+ (* y 3) x 1 ?0)))
(ttt-move)))))
)
)
@end example
The function takes 3 parameters, @code{p}, @code{e} and @code{m}. The
variable @code{p} is the position character in the buffer where the
mouse was clicked. (Same value as if (point) were called). This can be
used to determine where the user clicked. The variable @code{e}
contains the event as returned by the function @code{event-basic-type},
and the variable @code{m} contains the list returned by
@code{event-modifiers}. These contents are converted to text and sent
over a talk session when in tyrant-mode.
in the above example, we see a simple bit of math to calculate what
virtual square we clicked in. I've used this basic formula in almost
all of my games. The 'click feature is used in my games to perform some
sort of 'selection', and drags will just position the cursor.
@node Secret Messages, Asking Questions, Mouse Control, Writing Games
@section Secret Messages
In some situations, not all information is known to everyone. Classic
examples to this are card games, and games like word-thing. In these
instances, there must be ONLY ONE of the two etalk clients which keep
track of lists, hands, and information like that.
To handle this, you must set up a message handler, and declare player1
as the main bookkeeper. Here is a sample from hangman:
@example
(setq tyrant-player1-hook
'(lambda ()
(while (> (length hangman-to-guess-string) 30)
(setq hangman-to-guess-string
(read-string "Enter the word for remote to guess: "))
(message "Interpolating [%s]..." hangman-to-guess-string) )
(make-local-variable 'etalk-tyrant-brief-help)
(setq etalk-tyrant-brief-help
"Hangman : C-c m to send a minibuffer message, otherwise just watch.")
(setq etalk-tyrant-enabled-console nil) ;player 1 don't
;guess.
(hang-make-hangman-guess-string hangman-to-guess-string)
(goto-char 220) ;where the message should
;start
(kill-line)
(let ((game-lib-replace nil))
(game-lib-insert-string (point)
(concat " " hangman-guess-string)
nil))
(goto-char (point-max))
(insert "String to guess: " hangman-to-guess-string "\nGuessed chars: ")))
(setq tyrant-player2-hook
'(lambda ()
(setq etalk-tyrant-enabled-console nil)
(setq tyrant-call-interpreter 'hang-do-message)
(make-local-variable 'etalk-tyrant-brief-help)
(setq etalk-tyrant-brief-help
"Hangman : Press any lower case letter to guess. C-c m to send message.")
))
@end example
Here, under the player1 hook, the person who initiates get to choose the
word to guess under hangman. The function
@code{hangman-make-hangman-guess-string} converts the typed string, and
sends the message to the other user.
@refill
Under the player2 hook, we see more stuff about messaging in the setting
of @code{tyrant-call-interpreter} to the function
@code{hang-do-message}.
@refill
@findex tyrant-call-interpreter
Now, to actually send a string somewhere, simply use the function
@code{tyrant-send-message} which only takes one string. That string is
then modified and sent over the tcp connection to the other etalk
client.
@findex tyrant-send-message
The function assigned to @code{tyrant-call-interpreter} takes only one
parameter, and that is the string received from the remote. What you do
with these strings is up to you. In hangman, the string is the text
printed after the hangman diagram in which the text for the letters is
guessed. In word thing, the letters in a given hand are simple sent
over as a string. In the @file{card-lib.el} library, there is a cards
function designed to convert a stack of cards into a string, and parse
it back again.
@node Asking Questions, Gamelib functions, Secret Messages, Writing Games
@section Asking Questions in Tyrant Mode
@findex game-lib-query
Tyrant mode can only control those input characters typed into the game
buffers local map, because that is the map used for character
interpretation. As a result, if a program needs to ask a quesion, using
@code{read-string} or @code{(interactive "sSecret Code: ")} would ask
BOTH sides, when it is desirable for only the active player to make
those decisions. To this end, game-lib supplies a routine to read
strings for you.
@defun{game-lib-query (PROMPT INITIAL-INPUT COMPLETION-LIST)}
Queries user with prompt, starting with INITIAL-INPUT. It is important
to set INITIAL-INPUT to a valid string because that is the value used to
unlock the remote display in case of an error, or a user pressing C-g.
COMPLETION-LIST can be a symbol, which would read a plain string, or an
alist of valid strings to complete with.
If tyrant-mode is enabled, only the ACTIVE player will be asked the
question. The inactive player with be told that a question is being
asked. When the active player enters thier selection, the result is
sent to the inactive player, simulating that it had just been typed in.
@end defun
@node Gamelib functions, ,Asking Questions ,Writing Games
@section Game library functions
@cindex game-lib
@cindex etalk-tyrant
The variables which allow you to control features of tyrant-mode are:
@table @code
@item etalk-tyrant-enabled-console
Default value: nil . Variable for minor-mode alist, defining when the
tyrant console is enabled. This provides default value.
@item tyrant-player1-hook
Default value: nil. Hook used when starting up player 1's player space.
This should only be set by games who believe that they will be used
under tyrant mode.
@item tyrant-player2-hook
Default value: nil. Hook used when starting up player 2's player space.
This should only be set by games who believe that they will be used
under tyrant mode.
@item tyrant-mouse-function
Default value: nil. Function used to evaluate mouse actions locally in a
buffer.
@item tyrant-call-interpreter
Default value: nil. Function which can be set to evaluate message type 1
(game data). Allows games to play as master/slave where initiator knows
some piece of global/random data like cards of word-thing pieces.
@item etalk-tyrant-enabled-console
Default value: nil. For games with TURNS, this flag is set by game to
control playing. When this is NIL, key presses are not interpretted,
otherwise play can proceede as normal.
@item etalk-tyrant-brief-help
Default value: nil. C-h will print a tyrant help string unless this is
set in the game, then it prints a brief help message based on the game
rules.
@item etalk-tyrant-quit-string
Default value: nil. When a program is quit, and this has a value, then
print something like 'Eric wins!' before the hit return message.
@item tyrant-not-turn-message
Default value: nil. If set locally, the specified string is used instead
of 'it's not your turn' as per tyrant mode default.
@item tyrant-player-index
Default value: nil. Flag indicating who you are (player 1 means
initiator, player 2 means you agreed to a game request
@item tyrant-turn
Default value: nil. Contains local version of who's turn it is during a
tyrant controlled game. This allows tyrant-format to easily pring
strings based on turn so the game need not figure it out.
@item tyrant-dont-restore-position
Default value: nil. Set locally inside tyrant key press to allow games
to hook upward in removing where the cursor should be.
@end table
A function to be familiar with is @code{tyrant-format}. This function
will format a string with special tokens via the sformat driver. The
tokens allowed are:
@table @asis
@item %u
player one's username.
@item %U
player two's username.
@item %n
player one's preferred name.
@item %N
player two's preferred name.
@item %p
choose player based on local variable tyrant-turn.
@item %P
choose player based on local variable tyrant-turn and use pref name
@end table
The username is that persons login name, and a preferred name is that
found with the finger information.
The rest of the tyrant-mode features are used to invisibly simulate the
normal functioning of you game over a network.
game-lib control variables which you may use are:
@table @code
@item game-lib-replace
Default value: t. In most cases, we wish to replace characters for
games, rarely, we need a little hook in so we may insert (end of lines,
etc)
@item game-lib-use-colors
Default value: (Depends on your system). Set this to nil if you never
wish to use colors, otherwise, always use colors when you have windows
@end table
Some functions which are handy to use are:
@table @code
@item game-lib-load-color
Create a color for SYM with a L-FG and L-BG color, or D-FG and
D-BG, plus BOLD if applicable. If the background attribute of the
current frame is determined to be light (white, for example) then L-FG
and L-BG is used. If not, then D-FG and D-BG is used. This will
allocate the colors in the best possible mannor. This will allow me
to store multiple defaults and dynamically determine which colors to
use.
@item game-lib-add-mouse-support
Parameters: keymap. Adds mouse support to a game. It puts a call to
game-lib-handle-mouse into KEYMAP entries for FUNCTION which will be
used to handle the mouse events. This must be done this way so
mouse-related actions can be sent over the network. The event [mouse]
can't be transferred as a character.
FUNCTION should receive the list (p e m) where P is the position in
the buffer, and e is the event type (mouse-1, mouse-2, mouse-movement)
and m is a list of modifiers (down, click, drag, etc) Your average game
will probably skip many of these types.
@item game-lib-clear-buffer
Parameters: (&optional buffer). Take the current buffer and delete
everything in it. This also will delete any overlays existing in the
buffer.
@item game-lib-insert-string
Parameters: (pnt string color). Take STRING and place into buffer at
PNT, replaceing what was there, and making sure that face color is COLOR
(being a symbol containing a face) If the variable
@code{game-lib-replace} is non-nil, then also replace what was under the
text, up to the first new-line.
@item game-lib-win
Parameters: (who etalk-message solo-message). Declare WHO winner
handling tyrant problems. If tyranted, use the ETALK-MESSAGE,
otherwise, use SOLO-MESSAGE, where the etalk message contains
tyrant-format controls, and solo-message may contain one %d which will
be filled in by WHO. Just before printing the message, tyrant-turn is
set to WHO, thus allowing use of %P etc in tyrant messages even when it
isn't tyrant-turn's turn.
@item game-lib-swap-turns
Parameters: (etalk-message solo-message). Swap turns handling tyrant
problems. If tyranted, use the ETALK-MESSAGE, otherwise use
SOLO-MESSAGE, where the etalk messasge contains tyrant-format controls,
and solo-message may contain one %d which will be give the current turn
number.
@item game-lib-quit
Parameters: (kill). Covers over icky tyrant mode stuff needed to quit a
game. If KILL, then kill the buffer when done.
@end table
|