/*----------------------------------------------------*- Fundamental -*-
Facility: stone(6)
File: stone.c
Associated files: - (none)
Description: Plays the game of Kalah.
Notes: This program was originally available in two
versions, one for dumb terminals and ttys
(stone) and one for H19-type terminals
(hstone). The present version is a cleaned-
up implementation of hstone, adapted for a
curses-compatible terminal interface.
The program will only work on terminals with
at least 80 chars per line, and with at least
24 lines. The only reason for this limit
is the screen layout - see printb()
Portability: Edited to conform to X/Open Portability
Guide, ed. 3
Authors: Terry Hayes & Clark Baker
Real-Time Systems Group
MIT Lab for Computer Science
Editor: Leor Zolman
Anders Thulin
Rydsvagen 288
S-582 50 Linkoping
SWEDEN
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Edit history :
Vers Ed Date By Comments
---- --- ---------- ---------------- -------------------------------
1.0 0 19xx-xx-xx Hayes & Baker
1.1 1 19xx-xx-xx Leor Zolman
1.2 2 1990-03-25 Anders Thulin
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*--- Configuration options: ----------------------------------------
System configuration options:
=============================
ANSI ANSI C
BSD BSD Unix, SunOS 3.5
SV2 AT&T UNIX System V.2
XPG3 X/Open Portability Guide, ed. 3
If you have an ANSI C conformant compiler, define ANSI. If not, choose
the definition that most closely matches your environment.
Program configuration options:
==============================
TRACE This definition should not be changed. It is used to
remove all code that in the original version wrote
tracing information to the screen. As these completely
destroy the screen layout they have been removed.
A good way of including them in the program would be to
change them to write to a special trace window. This is
left as an exercise for the reader.
BEEP See 'comments' below
FUDGE (65) Used to determine the total number of game tree nodes
(game positions) to be examined -- computed as
FUDGE * chosen level of difficulty
MAX_LEVEL (1000)
The maximum level of difficulty allowed. FUDGE * MAX_LEVEL
should not be larger than INT_MAX.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#define ANSI 1
#define BSD 0
#define SV2 0
#define XPG3 0
#define TRACE 0
#define BEEP() beep()
#define FUDGE 32
#define MAX_LEVEL 1000
/* - - end of configuration options - - - - - - - - - - - - - - - - - - - */
#if ANSI
# include <ctype.h>
# include <curses.h>
# include <stdio.h>
# include <stdlib.h>
extern int getopt(int argc, char *argv[], char optstring[]);
extern int optind;
#endif
#if BSD
# include <ctype.h>
# include <curses.h>
# include <stdio.h>
extern int getopt();
extern int optind;
#endif
#if SV2
# include <ctype.h>
# include <curses.h>
# include <stdio.h>
extern int getopt();
extern int optind;
#endif
#if XPG3
# include <ctype.h>
# include <curses.h>
# include <stdio.h>
# include <stdlib.h>
extern int getopt();
extern int optind;
#endif
/*--- Comments on known problems: ------------------------------------------
curses
Some older implementation of curses does not have the beep()
function, which beeps at the user.
On such systems, you may need to define BEEP to produce a
beep in some other way, like fputc(0x07, stderr).
If you cannot beep at all, try to flash the screen.
If you cannot do either, just define BEEP to be empty, which is
permitted behaviour for curses' beep().
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/*--- Original notes on the program: -----------------------------------
"STONE"
(otherwise known as "Awari")
This version written by
Terry Hayes & Clark Baker
Real-Time Systems Group
MIT Lab for Computer Science
(and hacked up a little by Leor Zolman)
The algorithm used for STONE is a common one to Artificial Intelligence
people: the "Alpha-Beta" pruning heuristic. By searching up and down a tree
of possible moves and keeping record of the minimum and maximum scores from
the terminal static evaluations, it becomes possible to pinpoint move
variations which can in no way affect the outcome of the search. Thus,
those variations can be simply discarded, saving expensive static evaluation
time.
#if TRACE
To have the program print out some search statistics for every move
evaluation, type the command as
A> stone -d
To also see a move-by-move trace of each terminal evaluation, type
A> stones -a
#end
THIS is the kind of program that lets C show its stuff; Powerful expression
operators and recursion combine to let a powerful algorithm be implemented
painlessly.
And it's fun to play!
Rules of the game:
Each player has six pits in front of him and a "home" pit on one side (the
computer's home pit is on the left; your home pit is on the right.)
At the start of the game, all pits except the home pits are filled with n
stones, where n can be anything from 1 to 6.
To make a move, a player picks one of the six pits on his side of the board
that has stones in it, and redistributes the stones one-by-one going
counter-clockwise around the board, starting with the pit following the one
picked. The opponent's HOME pit is never deposited into.
If the LAST stone happens to fall in that player's home pit, he moves again.
If the LAST stone falls into an empty pit on the moving player's side of
board, then any stones in the pit OPPOSITE to that go into the moving
player's home pit.
When either player clears the six pits on his side of the board, the game is
over. The other player takes all stones in his six pits and places them in
his home pit. Then, the player with the most stones in his home pit is the
winner.
The six pits on the human side are numbered one to six from left to right;
the six pits on the computer's side are numbered one to six right-to-left.
The standard game seems to be with three stones; less stones make it
somewhat easier (for both you AND the computer), while more stones
complicate the game. As far as difficulty goes, well...it USED to be on a
scale of 1 to 50, but I couldn't win it at level 1. So I changed it to
1-300, and couldn't win at level 1. So I changed it to 1-1000, and if I
STILL can't win it at level 1, I think I'm gonna commit suicide.
Good Luck!!!
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Notes added by Anders Thulin:
The present program plays the game of Kalah. It does not play the game of
Oware, which has slightly more complicated rules. For a description of
Oware (as well as other games of the Mancala family), take a look at Ian
Lennox-Smith's series of articles in the British magazine Games & Puzzles,
no. 26-29 (July-October 1974), or any reliable book on board games (there
*are* unreliable ones!)
Kalah is usually played with 3-6 stones in each pit. The game with only one
stone in each pit is 'trivial' (won by the first player), as well as that
with two stones. It is reasonably easy to modify this program to check this
statement out.
There is an interesting paper on a learning implementation of Kalah in
Machine Intelligence vol. 3, ed. D. Michie, Edinburgh 1974. The paper is
written by A. G. Bell; the title is 'Kalah on Atlas'.
For a description of the alpha-beta pruning algorithm, see almost any
introductory work on artificial intelligence. A good description is given by
David Levy in The Chess Computer Handbook, Batsford, London 1984.
For an interestin