home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!zephyr.ens.tek.com!master!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v13i011: xmake5 - connect five-in-a-row game, Part02/03
- Message-ID: <2161@masterCNA.TEK.COM>
- Date: 13 Dec 91 22:21:33 GMT
- Sender: news@masterCNA.TEK.COM
- Lines: 1704
- Approved: billr@saab.CNA.TEK.COM
-
- Submitted-by: hsiehch@SPUNKY.CS.NYU.EDU (Chih-Hung Hsieh)
- Posting-number: Volume 13, Issue 11
- Archive-name: xmake5/Part02
- Environment: C++, X11, curses
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 3)."
- # Contents: Makefile bdconst.h debug.inc drawing.c helptext.C make5.C
- # make5.xbm record.c select.C xmake5.6 xmake5.doc
- # Wrapped by billr@saab on Fri Dec 13 14:14:56 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(2688 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X#! /bin/sh
- X#
- X# Makefile for xmake5 and cmake5.
- X#
- X# The folllowing directory and file names could be changed.
- X
- XSCOREDIR = ./Score
- X# where to put the high score file and its locker
- X
- XSCORE_F = $(SCOREDIR)/Make5.Score
- X# the high score file
- X
- XLOCK_F = $(SCOREDIR)/Make5.Score.lock
- X# the locker for the high score file, to prevent concurrent write
- X
- XBINDIR = ./Bin
- X# where to put the executable "xmake5" and "cmake5"
- X
- XMANDIR = ./Man
- X# where to put the man pages: "xmake5.6" and "cmake5.6"
- X
- XMAILER = /usr/ucb/mail -s Make5.Record
- X# the program that mails move records from cmake5
- X
- XCC = cc
- XCPP = CC
- X# You might want to use "gcc" and "g++".
- X
- X# ----------------------------------------------------------------
- X# Usually, you do not have to change anything below.
- X
- X
- XFILE_DEF = -DSCORE_FILE='"$(SCORE_F)"' \
- X -DLOCK_FILE='"$(LOCK_F)"' \
- X -DMAIL_COMMAND='"$(MAILER)"'
- X
- XXLIB = -lXaw -lXmu -lXt -lXext -lX11
- X
- XDEBUG = -O
- X
- XSOURCE = xmake5.c drawing.c xmake5.h record.c cmake5.C \
- X make5.xbm board.xbm printhelp.c helptext.C \
- X make5.C select.C debug.inc bdconst.h initbd.C \
- X line_val.inc Makefile COPYRIGHT README \
- X XMake5.ad xmake5.doc xmake5.6 cmake5.6
- X
- X
- XOBJS = xmake5.o drawing.o record.o make5.o select.o initbd.o helptext.o
- X
- XOBJS2 = cmake5.o record.o make5.o select.o initbd.o
- X
- X.SUFFIXES: .C
- X
- X.C.o:
- X $(CPP) $(DEBUG) -c $*.C
- X
- X.c.o:
- X $(CC) $(DEBUG) -c $*.c
- X
- Xall: cmake5 xmake5 xmake5.doc $(SCORE_F)
- X
- X$(BINDIR):
- X mkdir $(BINDIR)
- X
- X$(MANDIR):
- X mkdir $(MANDIR)
- X
- X$(SCOREDIR):
- X mkdir $(SCOREDIR)
- X
- Xxmake5.doc: printhelp
- X printhelp > xmake5.doc
- X
- Xcmake5: $(OBJS2)
- X $(CPP) $(DEBUG) -o cmake5 $(OBJS2) -lcurses -ltermcap
- X strip cmake5
- X chmod 04755 cmake5
- X
- X$(SCORE_F): $(SCOREDIR)
- X echo "Name Level Steps min:sec time date" \
- X > $(SCORE_F)
- X echo "-----------------------------------------------------" \
- X >> $(SCORE_F)
- X chmod 0644 $(SCORE_F)
- X
- Xprinthelp: printhelp.o helptext.o
- X $(CPP) -o printhelp printhelp.o helptext.o
- X strip printhelp
- X
- Xxmake5: $(OBJS)
- X $(CPP) $(DEBUG) -o xmake5 $(OBJS) $(XLIB)
- X strip xmake5
- X chmod 04755 xmake5
- X
- Xrecord.o: record.c
- X $(CC) $(DEBUG) -c $(FILE_DEF) record.c
- X
- Xcmake5.o: cmake5.C
- Xxmake5.o: xmake5.c make5.xbm xmake5.h
- Xdrawing.o: drawing.c board.xbm xmake5.h
- Xmake5.o: make5.C bdconst.h
- Xselect.o: select.C debug.inc bdconst.h
- Xinitbd.o: initbd.C line_val.inc bdconst.h
- X
- Xxmake5.shar: $(SOURCE)
- X shar $(SOURCE) > xmake5.shar
- X
- Xcleanup:
- X /bin/rm *.o cmake5 xmake5 printhelp
- X
- Xinstall: $(BINDIR) $(MANDIR) cmake5 xmake5 cmake5.6 xmake5.6
- X /bin/cp xmake5 cmake5 $(BINDIR)
- X /bin/cp xmake5.6 cmake5.6 $(MANDIR)
- X chmod 04755 $(BINDIR)/xmake5 $(BINDIR)/cmake5
- X chmod 0444 $(MANDIR)/xmake5.6 $(MANDIR)/cmake5.6
- END_OF_FILE
- if test 2688 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'bdconst.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bdconst.h'\"
- else
- echo shar: Extracting \"'bdconst.h'\" \(2343 characters\)
- sed "s/^X//" >'bdconst.h' <<'END_OF_FILE'
- X// FILE: bdconst.h
- X
- Xconst int
- X max_side_lev = 31 , max_index = 496 ,
- X max_line_lev = 20 , max_pt_lev = 27 ,
- X wall = '#', blank = '.' , black = 'X' , white = 'O' ,
- X bdwidth = 21 , bdlength = 440 ;
- X
- Xextern const int weight5[5], dirx[8];
- X
- Xconst int x_index_range = bdlength+1;
- X
- Xtypedef int x_index; // 0..bdlength ;
- Xtypedef char side_lev_range; // 0..max_side_lev ;
- Xtypedef int line_index; // 0..max_index ;
- Xtypedef char line_lev_range; // 1..max_line_lev ;
- Xtypedef char pt_lev_range; // 1..max_pt_lev ;
- Xtypedef line_lev_range line_val_type[max_index+1];
- X
- Xextern int weight31[31];
- X
- Xtypedef struct pt_lev_record_tag {
- X int pc[2][max_pt_lev+1];
- X int mp[2]; // { 1..max_pt_lev }
- X} pt_lev_record;
- X
- Xtypedef struct bdstatus_type_tag {
- X side_lev_range side_lev[x_index_range][2][8];
- X line_lev_range line_lev[x_index_range][2][4];
- X pt_lev_range point_lev[x_index_range][2];
- X pt_lev_record pt_lev_rec;
- X} bdstatus_type;
- X
- Xextern int min_depth,max_depth; // depths of MIN/MAX search
- X
- Xextern const pt_lev_range point_lev_tab[max_line_lev+1][max_line_lev+1];
- X// initialized in "initbd.C"
- X
- Xtypedef struct update_record_tag {
- X int side_lev, line_lev;
- X pt_lev_range point_lev;
- X} update_record[2][8][5] ; // array[1..2,-4..4,1..5]
- X
- Xextern char board[x_index_range];
- Xextern bdstatus_type bdstatus;
- X
- Xextern int player;
- Xextern char player_color[2];
- Xextern int step;
- X
- X#define x_col(x) (x % bdwidth)
- X#define x_row(x) (x / bdwidth)
- X#define dec(x) ((x)--)
- X#define inc(x) ((x)++)
- X
- X//---------------------------------------------------------------------------
- X// Procedures defined in "initbd.C"
- X
- Xextern void init_bdstatus(void);
- Xextern int get_side_lev(int x,int d,char c);
- Xextern void set_side_lev(int x);
- Xextern void set_line_lev(int x,int c,int d);
- Xextern void set_point_lev(int x, int c);
- X
- X//---------------------------------------------------------------------------
- X// Procedures defined in "make5.C"
- X
- Xextern void update_board(int sw, int x, update_record *z, pt_lev_record *pt);
- Xextern void restore(int x, update_record *z, pt_lev_record *pt);
- Xextern update_record *new_update_record(void);
- Xextern pt_lev_record *new_pt_lev_record(void);
- X
- X//---------------------------------------------------------------------------
- END_OF_FILE
- if test 2343 -ne `wc -c <'bdconst.h'`; then
- echo shar: \"'bdconst.h'\" unpacked with wrong size!
- fi
- # end of 'bdconst.h'
- fi
- if test -f 'debug.inc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'debug.inc'\"
- else
- echo shar: Extracting \"'debug.inc'\" \(171 characters\)
- sed "s/^X//" >'debug.inc' <<'END_OF_FILE'
- X// FILE: "debug.inc"
- X
- X#define Check_No_Point(a,b)
- X
- X// void Check_No_Point(char *s, point_list &p) {
- X// if (p.n<=0) {printf("Error: %s\n",s); exit(1); }
- X// }
- END_OF_FILE
- if test 171 -ne `wc -c <'debug.inc'`; then
- echo shar: \"'debug.inc'\" unpacked with wrong size!
- fi
- # end of 'debug.inc'
- fi
- if test -f 'drawing.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'drawing.c'\"
- else
- echo shar: Extracting \"'drawing.c'\" \(11087 characters\)
- sed "s/^X//" >'drawing.c' <<'END_OF_FILE'
- X/* FILE: drawing.c (Ver. 1.1) */
- X
- X#include <X11/cursorfont.h>
- X#include <X11/Intrinsic.h>
- X#include <X11/StringDefs.h>
- X
- X#include <stdio.h>
- X/**********************************************************************/
- X
- X#include "xmake5.h"
- X#include "board.xbm"
- X
- XDisplay *display;
- Xint screen_num;
- Xunsigned long black_color, white_color;
- XCursor cursor;
- X
- X/**********************************************************************/
- X/* All about drawing */
- X
- XWindow main_win;
- Xstatic Pixmap board_map;
- X
- Xstatic unsigned board_x0, board_x1, board_y0, board_y1;
- Xstatic unsigned stone_x0, stone_y0;
- Xstatic unsigned cell_height, cell_width;
- Xstatic unsigned stone_size_x, stone_size_y;
- X
- Xstatic int min_main_win_width=396, min_main_win_height=396;
- Xstatic int main_win_width=0, main_win_height=0;
- X
- Xstatic XColor C1W,C1B;
- Xstatic GC gc, gc_stone[2], gc_board, gc_back;
- X
- Xchar board_stones[BoardLines][BoardLines];
- X
- X/**********************************************************************/
- X/* All about drawing, Xlib */
- X/**********************************************************************/
- Xvoid warp_to_position(x,y) int x,y;
- X{ /* move the pointer out and back the main_window */
- X XWarpPointer(display,NULL,main_win,0,0,0,0,-1,-1);
- X XWarpPointer(display,NULL,main_win,0,0,0,0,
- X board_x0 + x * cell_width, board_y0 + y * cell_height);
- X}
- X/**********************************************************************/
- Xvoid refresh_pointer()
- X{ Window r_win, c_win;
- X int r_x, r_y, w_x, w_y;
- X unsigned int keys;
- X XQueryPointer(display,main_win,&r_win,&c_win,&r_x,&r_y,&w_x,&w_y,&keys);
- X /* move the pointer out and back the main_window */
- X XWarpPointer(display,NULL,main_win,0,0,0,0,-1,-1);
- X XWarpPointer(display,NULL,main_win,0,0,0,0,w_x,w_y);
- X}
- X/**********************************************************************/
- Xvoid to_last_position()
- X{ int x;
- X if (last_move_rec <= 0) warp_to_position(9,9);
- X else {
- X x = move_rec[last_move_rec];
- X warp_to_position(BoardX(x),BoardY(x));
- X }
- X}
- X/**********************************************************************/
- Xvoid switch_color(c) int c;
- X{
- X if (c==0) XRecolorCursor(display,cursor,&C1B,&C1W);
- X else XRecolorCursor(display,cursor,&C1W,&C1B);
- X refresh_pointer();
- X}
- X/**********************************************************************/
- Xvoid draw_suggestions()
- X{ int i,n,x;
- X
- X for (i=0,n=num_of_suggestion; i<n; i++) {
- X x=suggest_position[i];
- X mark_stone(BoardX(x),BoardY(x),player);
- X }
- X }
- X/**********************************************************************/
- Xstatic void reconfig_board(redraw) int redraw;
- X{
- X board_x0 = 2 * cell_width;
- X board_y0 = 2 * cell_height;
- X board_x1 = (BoardLines+1) * cell_width;
- X board_y1 = (BoardLines+1) * cell_height;
- X stone_size_x = cell_width * 4 / 5;
- X stone_size_y = cell_height * 4 / 5;
- X stone_x0 = board_x0 - (stone_size_x/2);
- X stone_y0 = board_y0 - (stone_size_y/2);
- X if (redraw) redraw_board();
- X}
- X/**********************************************************************/
- Xstatic void set_new_board_size(w,h) int w,h;
- X{ Dimension width,height,bw;
- X Arg args[3];
- X XtSetArg(args[0], XtNwidth, &width);
- X XtSetArg(args[1], XtNheight, &height);
- X XtSetArg(args[2], XtNborderWidth, &bw);
- X XtGetValues(toplevel, args, 3);
- X width = width + w - main_win_width;
- X height = height + h - main_win_height;
- X XtResizeWidget(toplevel,width,height,bw);
- X}
- X/**********************************************************************/
- Xvoid adjust_board()
- X{ int mw = max(cell_width,cell_height) * (BoardLines + 3);
- X
- X if (mw < min_main_win_width || mw < min_main_win_height)
- X mw += BoardLines + 3;
- X if (cell_width != cell_height ||
- X main_win_width != mw || main_win_height != mw )
- X set_new_board_size(mw,mw);
- X}
- X/**********************************************************************/
- Xvoid Board_config(w, event, params, num_params)
- X Widget w;
- X XConfigureEvent *event;
- X String *params;
- X Cardinal *num_params;
- X{ int new_width, new_height, enlarge;
- X
- X enlarge = event->width > main_win_width ||
- X event->height > main_win_height ;
- X main_win_width = event->width;
- X main_win_height = event->height;
- X new_width = max(main_win_width, min_main_win_width);
- X new_height = max(main_win_height, min_main_win_height);
- X if (main_win_width != new_width ||
- X main_win_height != new_height) {
- X set_new_board_size(new_width,new_height);
- X return;
- X }
- X cell_width = main_win_width / (BoardLines + 3);
- X cell_height = main_win_height / (BoardLines + 3);
- X reconfig_board(!enlarge);
- X /* When the window is enlarged,
- X a further redraw event will redraw the board. */
- X}
- X/**********************************************************************/
- Xvoid Board_redraw(w, event, params, num_params)
- X Widget w;
- X XExposeEvent *event;
- X String *params;
- X Cardinal *num_params;
- X{
- X if (event->count == 0) redraw_board();
- X}
- X/**********************************************************************/
- Xvoid Board_seton(w, event, params, num_params)
- X Widget w;
- X XButtonEvent *event;
- X String *params;
- X Cardinal *num_params;
- X{
- X int xpos, ypos, xp, yp, movex;
- X
- X if (game_over) return;
- X if (player_name[player] != 'M') {
- X check_computer_move();
- X return; /* not for human player */
- X }
- X xpos = event->x;
- X ypos = event->y;
- X xypos_to_board_pos(xpos,ypos,&xp,&yp);
- X if (xp < BoardLines && board_stones[xp][yp] == empty_stone) {
- X movex = xp + 1 + (yp+1) * BoardSize;
- X make_a_move(movex);
- X check_computer_move();
- X }
- X}
- X/**********************************************************************/
- Xvoid setup_gc()
- X{
- X unsigned long valuemask = 0; /* ignore XGCvalues and use defaults */
- X XGCValues values;
- X Colormap cmap;
- X XColor C2W,C2B,C1G,C2G;
- X
- X cursor = XCreateFontCursor(display, XC_dot);
- X XDefineCursor(display, main_win, cursor);
- X
- X cmap=DefaultColormap(display,screen_num);
- X XAllocNamedColor(display, cmap, "black", &C1B, &C2B);
- X XAllocNamedColor(display, cmap, "white", &C1W, &C2W);
- X XAllocNamedColor(display, cmap, "LightGray", &C1G, &C2G);
- X black_color = BlackPixel(display,screen_num);
- X white_color = WhitePixel(display,screen_num);
- X
- X gc = XCreateGC(display, main_win, valuemask, &values);
- X XSetForeground(display, gc, black_color);
- X
- X gc_board = XCreateGC(display, main_win, valuemask, &values);
- X if (C1G.pixel == 0) {
- X board_map = XCreateBitmapFromData(display, main_win,
- X board_bits, board_width, board_height);
- X XSetFillStyle(display, gc_board, FillTiled);
- X XSetTile(display, gc_board, board_map);
- X } else {
- X XSetForeground(display, gc_board, C1G.pixel);
- X }
- X
- X gc_back = XCreateGC(display, main_win, valuemask, &values);
- X XSetForeground(display, gc_back, white_color);
- X
- X gc_stone[0] = XCreateGC(display, main_win, valuemask, &values);
- X gc_stone[1] = XCreateGC(display, main_win, valuemask, &values);
- X XSetForeground(display, gc_stone[0], black_color);
- X XSetBackground(display, gc_stone[0], white_color);
- X XSetForeground(display, gc_stone[1], white_color);
- X XSetBackground(display, gc_stone[1], black_color);
- X}
- X/**********************************************************************/
- Xdraw_H_line(y) int y;
- X{ unsigned y1 = board_y0 + y * cell_height;
- X
- X XDrawLine(display, main_win, gc, board_x0, y1, board_x1, y1);
- X}
- X/**********************************************************************/
- Xdraw_V_line(x) int x;
- X{ unsigned x1 = board_x0 + x * cell_width;
- X
- X XDrawLine(display, main_win, gc, x1, board_y0, x1, board_y1);
- X}
- X/**********************************************************************/
- Xput_stone(x,y,c) int x,y,c;
- X{ unsigned xp = stone_x0 + x * cell_width;
- X unsigned yp = stone_y0 + y * cell_height;
- X
- X board_stones[x][y] = c;
- X XFillArc(display,main_win,gc_stone[c],xp,yp,
- X stone_size_x,stone_size_y,0,360*64);
- X XDrawArc(display,main_win,gc_stone[1-c],xp,yp,
- X stone_size_x,stone_size_y,0,360*64);
- X}
- X/**********************************************************************/
- Xvoid unmark_last_move()
- X{ int x = move_rec[last_move_rec];
- X if (last_move_rec <= 0) return;
- X put_stone(BoardX(x), BoardY(x), 1-player);
- X}
- X/**********************************************************************/
- Xvoid mark_last_move()
- X{ int m = move_rec[last_move_rec];
- X unsigned xp,yp;
- X
- X if (last_move_rec <= 0) return;
- X xp = stone_x0 + BoardX(m) * cell_width;
- X yp = stone_y0 + BoardY(m) * cell_height;
- X XDrawArc(display,main_win,gc_stone[player],xp+3,yp+3,
- X stone_size_x-6,stone_size_y-6,0,360*64);
- X}
- X/**********************************************************************/
- Xclear_mark_stone()
- X{
- X if (num_of_suggestion > 0) {
- X num_of_suggestion = 0;
- X redraw_board_only();
- X }
- X}
- X/**********************************************************************/
- Xmark_stone(x,y,c) int x,y,c;
- X{ unsigned xp = stone_x0 + x * cell_width;
- X unsigned yp = stone_y0 + y * cell_height;
- X
- X XDrawArc(display,main_win,gc_stone[c],xp,yp,
- X stone_size_x,stone_size_y,0,360*64);
- X XDrawArc(display,main_win,gc_stone[c],xp-1,yp-1,
- X stone_size_x+2,stone_size_y+2,0,360*64);
- X}
- X/**********************************************************************/
- Xredraw_board_only()
- X{ int i,j;
- X
- X XFillRectangle(display, main_win, gc_back,
- X 0, 0, main_win_width, main_win_height);
- X
- X XFillRectangle(display, main_win, gc_board,
- X cell_width, cell_height,
- X main_win_width - 2 * cell_width,
- X main_win_height - 2 * cell_height);
- X
- X for (i=0; i < BoardLines; i++) {
- X draw_H_line(i);
- X draw_V_line(i);
- X }
- X
- X for (i=0; i < BoardLines; i++)
- X for (j=0; j < BoardLines; j++)
- X switch (board_stones[i][j]) {
- X case white_stone: put_stone(i,j,1); break;
- X case black_stone: put_stone(i,j,0); break;
- X default: break;
- X }
- X if (num_of_suggestion != 0) draw_suggestions();
- X mark_last_move();
- X}
- X/**********************************************************************/
- Xredraw_board()
- X{ redraw_board_only();
- X update_status();
- X}
- X/**********************************************************************/
- Xint near_cross_point(x) float x;
- X{ int k;
- X float dis = 0.35;
- X
- X if (x < - dis || x > (BoardLines - 1 + dis)) return 0;
- X k = x;
- X if (((x - k) < dis) || ((k + 1 - x) < dis)) return 1;
- X return 0;
- X}
- X/**********************************************************************/
- Xxypos_to_board_pos(xpos,ypos,xp,yp) int xpos, ypos, *xp, *yp;
- X{ float x=xpos, y=ypos;
- X
- X x = (x / cell_width) - 2;
- X y = (y / cell_height) - 2;
- X if (near_cross_point(x) && near_cross_point(y)) {
- X *xp = x + 0.5;
- X *yp = y + 0.5;
- X } else {
- X *xp = BoardLines;
- X *yp = BoardLines;
- X }
- X}
- X/**********************************************************************/
- END_OF_FILE
- if test 11087 -ne `wc -c <'drawing.c'`; then
- echo shar: \"'drawing.c'\" unpacked with wrong size!
- fi
- # end of 'drawing.c'
- fi
- if test -f 'helptext.C' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'helptext.C'\"
- else
- echo shar: Extracting \"'helptext.C'\" \(4387 characters\)
- sed "s/^X//" >'helptext.C' <<'END_OF_FILE'
- Xextern char *helptext =
- X
- X"Name of the game:\n"
- X"=================\n"
- X"\n"
- X"Make5 is a game similar to Tic-Tac-Toe.\n"
- X"It is called Wu3-Zi3-Qi2 in Chinese and is \n"
- X"very popular in the Far East. 5-in-a-row and\n"
- X"Go-Moku are the other names for this game.\n"
- X"You may also find it called \"Chess\" on some\n"
- X"Nitendo games. I call it Make5 because the goal\n"
- X"of this game is to make five continuous stones\n"
- X"in a line.\n"
- X"\n\n"
- X"How to play:\n"
- X"============\n"
- X"\n"
- X"This game was originally played by two players\n"
- X"on a board of infinite size. Each player puts\n"
- X"a stone at one empty cross-point at a time. \n"
- X"The winner is the one who first puts five\n"
- X"continuous stones in a line, vertically, \n"
- X"orizontally, or diagonally.\n"
- X"\n"
- X"However, this program plays the game on a finite\n"
- X"board the same size as a GO game board, which has\n"
- X"19 by 19 cross-points. The only tricky rule is\n"
- X"that you must make exactly five continuous stones\n"
- X"in a line to win. Six or more stones in a line\n"
- X"do not count.\n"
- X"\n"
- X"Some people play this game with a rule which\n"
- X"prohibits the first player to make double-3 or \n"
- X"double-4 attacking patterns. But I do not\n"
- X"like this rule and did not include it in this \n"
- X"program.\n"
- X"\n\n"
- X"Strategies:\n"
- X"===========\n"
- X"\n"
- X"So, you see why it is like Tic-Tac-Toe. \n"
- X"You have to stop the other player\'s continuous \n"
- X"lines of stones and design your own attacking lines.\n"
- X"Unlike Tic-Tac-Toe, this game is played on a large\n"
- X"board and requires five stones in a line to win. \n"
- X"Is there a winning strategy for the first player? \n"
- X"You tell me.\n"
- X"\n\n"
- X"Options of playing:\n"
- X"===================\n"
- X"\n"
- X"This program can play with you or play with itself. \n"
- X"You can also play with your friends and use this\n"
- X"program to update the board.\n"
- X"\n"
- X"Most of the options in the \"Setup...\" menu can be\n"
- X"changed in the middle of a game. Hence, you can\n"
- X"switch the players, change the computer's searching\n"
- X"level, or even undo your moves.\n"
- X"The \"Where...\" menu provides hints for good\n"
- X"positions and the position of the last move.\n"
- X"\n"
- X"You can switch to the challenge mode, in which\n"
- X"the computer always moves first and you can not\n"
- X"undo, change play level or order, or get suggestion\n"
- X"from the computer. If you beat the computer, your\n"
- X"name would be added into the list of winners.\n"
- X"\n"
- X"Have fun!\n"
- X"\n\n"
- X"History of this program:\n"
- X"========================\n"
- X"\n"
- X"The basic playing algorithm was designed in 1984\n"
- X"as a term project of an A.I. class; it was written\n"
- X"in Pascal and runs on Prime-750. The game was\n"
- X"ported to Turbo Pascal and ran on PC in 1986.\n"
- X"\n"
- X"Now this game is translated to C and C++ with an\n"
- X"X interface. Another version called cmake5 is also\n"
- X"available. It uses the UNIX curses library and runs\n"
- X"on most ASCII terminals.\n"
- X"\n"
- X"\n"
- X"Chih-Hung Hsieh November 1991\n"
- X"\n"
- X"(Please send your comment to hsiehch@cs.nyu.edu.)\n"
- X"\n\n\n"
- X" Hsieh \n"
- X"------------------------ \n"
- X" ,,, ||' ||' \n"
- X" '|| ,,|,,,| || \n"
- X",,,,|,|, || || || \n"
- X" ||'''|| ,,,||,| \n"
- X" ,,,,|, ||,,,|| || \n"
- X" || ||,, || \n"
- X" '''''' || ,,||' || \n"
- X" , '||'' ,|| | || \n"
- X" ||''|| ,|'|| | || \n"
- X" || || ,,'' || || \n"
- X" || || || || \n"
- X" ||'''' ''||' ''||' \n"
- X"------------------------ \n"
- X" Chih \n"
- X"------------------------ \n"
- X" ||' \n"
- X" || ,, \n"
- X" '''''''''''||'''''''''''\n"
- X" || \n"
- X" || ,, \n"
- X" '''''''''''''''''''' \n"
- X" ,, \n"
- X" , ||' '|, ,, \n"
- X" | || '' '|, \n"
- X" ,|' || | '|| \n"
- X" ,|| || |, ||'\n"
- X" '' '|||||||||||' \n"
- X"------------------------ \n"
- X" Hung \n"
- X"------------------------ \n"
- X",,,,,,,,,|, ||, \n"
- X" ||' || \n"
- X" || || \n"
- X"|,,,,,,|| ,|' \n"
- X"|| '' || \n"
- X"|| || \n"
- X"||,,,,,,|, || \n"
- X"'' ||' |' ', \n"
- X" || |' '| \n"
- X" ,|' ,' ,|| \n"
- X" ,|' ,,|,,,|''' '|| \n"
- X"'''|||' '''' || \n"
- X"------------------------ \n"
- X;
- END_OF_FILE
- if test 4387 -ne `wc -c <'helptext.C'`; then
- echo shar: \"'helptext.C'\" unpacked with wrong size!
- fi
- # end of 'helptext.C'
- fi
- if test -f 'make5.C' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'make5.C'\"
- else
- echo shar: Extracting \"'make5.C'\" \(5243 characters\)
- sed "s/^X//" >'make5.C' <<'END_OF_FILE'
- X// FILE: make5.C (Ver. 1.0)
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X
- X#include "bdconst.h"
- X
- X//---------------------------------------------------------------------------
- Xconst int max_step = 175; // maximum move steps for each player
- X
- Xextern int player,step; // defined in make5x.c
- Xchar player_color[2];
- X
- X#define abs_d(d) ((d<4)?d:(7-d))
- X
- X//---------------------------------------------------------------------------
- Xupdate_record *new_update_record(void) {
- X char *p;
- X if ((p=(char *)malloc(2*8*5*sizeof(struct update_record_tag)))==NULL) {
- X printf("Out of Heap space in new_update_record\n"); exit(1);
- X }
- X return((update_record*)p);
- X}
- X//---------------------------------------------------------------------------
- Xpt_lev_record *new_pt_lev_record(void) {
- X char *p;
- X if ((p=(char*)malloc(sizeof(struct pt_lev_record_tag)))==NULL) {
- X printf("Out of Heap space in new_pt_lev_record\n"); exit(1);
- X }
- X return((pt_lev_record*)p);
- X}
- X//---------------------------------------------------------------------------
- Xvoid update_board(int sw, int x, update_record *z, pt_lev_record *pt) {
- X // update board status and save update record to z
- X int c,d,k,i;
- X *pt = bdstatus.pt_lev_rec;
- X if (sw == 1)
- X for (i=0; i<2; i++)
- X dec(bdstatus.pt_lev_rec.pc[i][bdstatus.point_lev[x][i]]);
- X else for (i=0; i<2; i++)
- X inc(bdstatus.pt_lev_rec.pc[i][bdstatus.point_lev[x][i]]);
- X for (d=0; d<8; d++) {
- X i = x;
- X for (k=0; k<5; k++) {
- X i += dirx[d];
- X if (board[i] == blank) {
- X for (c=0; c<2; c++) {
- X struct update_record_tag &zcdk = (*z)[c][d][k];
- X dec(bdstatus.pt_lev_rec.pc[c][bdstatus.point_lev[i][c]]);
- X zcdk.side_lev = bdstatus.side_lev[i][c][7-d];
- X zcdk.line_lev = bdstatus.line_lev[i][c][abs_d(d)];
- X zcdk.point_lev = bdstatus.point_lev[i][c];
- X bdstatus.side_lev[i][c][7-d] = get_side_lev(i,7-d,player_color[c]);
- X set_line_lev(i,c,abs_d(d));
- X set_point_lev(i,c);
- X inc(bdstatus.pt_lev_rec.pc[c][bdstatus.point_lev[i][c]]);
- X }
- X }
- X }
- X }
- X for (i=0; i<2; i++) {
- X bdstatus.pt_lev_rec.mp[i] = 1;
- X while (bdstatus.pt_lev_rec.pc[i][bdstatus.pt_lev_rec.mp[i]] == 0)
- X (bdstatus.pt_lev_rec.mp[i])++;
- X }
- X}
- X//---------------------------------------------------------------------------
- Xvoid restore(int x, update_record *z, pt_lev_record *pt) {
- X // restore board status with update_record z
- X int c,d,k,i;
- X bdstatus.pt_lev_rec = *pt;
- X for (d=0; d<8; d++) {
- X i = x;
- X for (k=0; k<5; k++) {
- X i += dirx[d];
- X if (board[i] == blank)
- X for (c=0; c<2; c++) {
- X struct update_record_tag &zcdk = (*z)[c][d][k];
- X bdstatus.side_lev[i][c][7-d] = zcdk.side_lev;
- X bdstatus.line_lev[i][c][abs_d(d)] = zcdk.line_lev;
- X bdstatus.point_lev[i][c] = zcdk.point_lev;
- X }
- X }
- X }
- X}
- X//---------------------------------------------------------------------------
- Xextern "C" void set_on(int x, int p) { // set on position x for player p
- X update_record *z = new_update_record();
- X pt_lev_record *pt = new_pt_lev_record();
- X board[x] = player_color[p]; // update board status
- X update_board(1,x,z,pt);
- X free(z); free(pt);
- X}
- X//---------------------------------------------------------------------------
- Xextern "C" void take_out(int x) { // take out the stone at x
- X update_record *z = new_update_record();
- X pt_lev_record *pt = new_pt_lev_record();
- X board[x] = blank;
- X update_board(0,x,z,pt);
- X free(z); free(pt);
- X}
- X//---------------------------------------------------------------------------
- Xstatic const int point3 = 13;
- Xstatic char *warning[] =
- X {"",
- X "***** GAME OVER ***** Five in a line.", // 1
- X "Warning: open 4-in-a-line and more !!!!!!", // 2
- X "Warning: open 4-in-a-line !!!!!!", // 3
- X "Warning: 4-in-a-line & open 3-in-a-line !!!!!", // 4
- X "Warning: Double open-3-in-a-line !!!!", // 5
- X "Warning: 4-in-a-line !!", // 6
- X "Warning: open 3-in-a-line !!", // 7
- X "Warning: 4-in-a-line !!", // 8
- X "Warning: open 3-in-a-line !!",
- X "Warning: 4-in-a-line !!",
- X "Warning: open 3-in-a-line !!",
- X "Warning: 4-in-a-line !!",
- X "Warning: open 3-in-a-line !!"};
- X//---------------------------------------------------------------------------
- Xextern "C" char *get_warning(int p,int x) {
- X int lev = bdstatus.point_lev[x][p];
- X if (step >= max_step)
- X return "***** GAME OVER ***** Too many steps. Tie!!";
- X if (lev <= point3) return warning[lev];
- X else return "";
- X}
- X//---------------------------------------------------------------------------
- Xextern "C" int is_game_over(int p,int x) {
- X return (bdstatus.point_lev[x][p] == 1 || step >= max_step);
- X}
- X//---------------------------------------------------------------------------
- Xextern "C" void init_data(void) {
- X init_bdstatus();
- X player_color[0]=black;
- X player_color[1]=white;
- X}
- X//---------------------------------------------------------------------------
- END_OF_FILE
- if test 5243 -ne `wc -c <'make5.C'`; then
- echo shar: \"'make5.C'\" unpacked with wrong size!
- fi
- # end of 'make5.C'
- fi
- if test -f 'make5.xbm' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'make5.xbm'\"
- else
- echo shar: Extracting \"'make5.xbm'\" \(2879 characters\)
- sed "s/^X//" >'make5.xbm' <<'END_OF_FILE'
- X#define make5_width 63
- X#define make5_height 56
- Xstatic char make5_bits[] = {
- X 0x31, 0x91, 0x11, 0x13, 0x19, 0x31, 0x91, 0x91, 0x22, 0xe2, 0x23, 0x22,
- X 0x2a, 0x22, 0xe2, 0xa3, 0xa8, 0x18, 0x8c, 0x8a, 0x88, 0xa8, 0x18, 0x8c,
- X 0x64, 0x0c, 0x48, 0x46, 0x4c, 0x64, 0x0c, 0xc8, 0xff, 0x0f, 0xf8, 0xff,
- X 0xff, 0xff, 0x0f, 0xf8, 0x22, 0x0a, 0x28, 0x22, 0x2a, 0x22, 0x0a, 0xa8,
- X 0xa8, 0x08, 0x88, 0x8a, 0x88, 0xa8, 0x08, 0x88, 0x64, 0x14, 0x44, 0x46,
- X 0x4c, 0x64, 0x14, 0xc4, 0x31, 0xf1, 0x13, 0x13, 0x19, 0x31, 0xf1, 0x93,
- X 0x22, 0xa2, 0x22, 0x22, 0x2a, 0x22, 0xa2, 0xa2, 0xa8, 0x88, 0x08, 0x80,
- X 0x88, 0x00, 0x88, 0x88, 0x64, 0xc4, 0x84, 0x4f, 0x4c, 0xf8, 0xc4, 0xc4,
- X 0x31, 0x91, 0xd1, 0x1f, 0x19, 0xfd, 0x91, 0x91, 0xff, 0xff, 0xdf, 0xdf,
- X 0xff, 0xfd, 0xfd, 0xff, 0xa8, 0x88, 0xc8, 0x9f, 0x88, 0xfc, 0x89, 0x88,
- X 0x64, 0xc4, 0xc4, 0x5f, 0x4c, 0xfc, 0xc5, 0xc4, 0x31, 0x91, 0x91, 0x0f,
- X 0x19, 0xf9, 0x90, 0x91, 0x22, 0xa2, 0x22, 0x20, 0x2a, 0x02, 0xa2, 0xa2,
- X 0xa8, 0x88, 0x88, 0x8a, 0x88, 0xa8, 0x88, 0x88, 0x64, 0xc4, 0xc4, 0x4f,
- X 0x40, 0x64, 0xc4, 0xc4, 0x31, 0x91, 0x51, 0x10, 0x3e, 0x31, 0x91, 0x91,
- X 0x22, 0xa2, 0x22, 0x20, 0x7f, 0x22, 0xa2, 0xa2, 0xff, 0xff, 0x3f, 0x60,
- X 0x7f, 0xff, 0xff, 0xff, 0x64, 0xc4, 0x24, 0x60, 0x7f, 0x64, 0xc4, 0xc4,
- X 0x31, 0x91, 0x31, 0x20, 0x7f, 0x31, 0x91, 0x91, 0x22, 0xa2, 0x62, 0x30,
- X 0x3e, 0x22, 0xa2, 0xa2, 0xa8, 0x88, 0x88, 0x8f, 0x80, 0xa8, 0x88, 0x88,
- X 0x64, 0xc4, 0x44, 0x46, 0x4c, 0x64, 0xc4, 0xc4, 0x31, 0x91, 0x11, 0x10,
- X 0x3f, 0x01, 0x91, 0x91, 0x22, 0xa2, 0xa2, 0x2f, 0x41, 0xfa, 0xa2, 0xa2,
- X 0xa8, 0x88, 0xc8, 0x9f, 0x80, 0xfc, 0x89, 0x88, 0xff, 0xff, 0xdf, 0xdf,
- X 0x80, 0xfd, 0xfd, 0xff, 0x31, 0x91, 0xd1, 0x9f, 0x80, 0xfd, 0x91, 0x91,
- X 0x22, 0xa2, 0xc2, 0x9f, 0x80, 0xfc, 0xa1, 0xa2, 0xa8, 0x88, 0x88, 0x8f,
- X 0xc1, 0xf8, 0x88, 0x88, 0x64, 0xc4, 0x44, 0x40, 0x7e, 0x04, 0xc4, 0xc4,
- X 0x31, 0x91, 0x11, 0x13, 0x19, 0x31, 0x91, 0x91, 0x22, 0x02, 0x20, 0x22,
- X 0x3e, 0x22, 0xa2, 0xa2, 0xa8, 0xe8, 0x8b, 0x8a, 0xc1, 0xa8, 0x88, 0x88,
- X 0x64, 0xf4, 0x47, 0xc6, 0x80, 0x64, 0xc4, 0xc4, 0xff, 0xf7, 0xf7, 0xff,
- X 0x80, 0xff, 0xff, 0xff, 0x22, 0xf2, 0x27, 0xa2, 0x80, 0x22, 0xa2, 0xa2,
- X 0xa8, 0xf0, 0x87, 0x8a, 0x80, 0xa8, 0x88, 0x88, 0x64, 0xe4, 0x43, 0x46,
- X 0x41, 0x64, 0xc4, 0xc4, 0x31, 0x11, 0x10, 0x13, 0x3f, 0x31, 0x91, 0x91,
- X 0x22, 0xa2, 0x22, 0x22, 0x2a, 0x22, 0xa2, 0xa2, 0xf8, 0x88, 0x88, 0x8a,
- X 0x88, 0xa8, 0x88, 0x88, 0x04, 0xc5, 0x44, 0x46, 0x4c, 0x64, 0xc4, 0xc4,
- X 0x03, 0x92, 0x11, 0x13, 0x19, 0x31, 0x91, 0x91, 0x03, 0xfe, 0xff, 0xff,
- X 0xff, 0xff, 0xff, 0xff, 0x02, 0x8a, 0x88, 0x8a, 0x88, 0xa8, 0x88, 0x88,
- X 0x02, 0xc6, 0x44, 0x46, 0x4c, 0x64, 0xc4, 0xc4, 0x05, 0x91, 0x11, 0x13,
- X 0x19, 0x31, 0x91, 0x91, 0xfa, 0xa2, 0x22, 0x22, 0x2a, 0x22, 0xa2, 0xa2,
- X 0xa8, 0x88, 0x88, 0x8a, 0x88, 0xa8, 0x88, 0x88, 0x64, 0xc4, 0x44, 0x46,
- X 0x4c, 0x64, 0xc4, 0xc4};
- END_OF_FILE
- if test 2879 -ne `wc -c <'make5.xbm'`; then
- echo shar: \"'make5.xbm'\" unpacked with wrong size!
- fi
- # end of 'make5.xbm'
- fi
- if test -f 'record.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'record.c'\"
- else
- echo shar: Extracting \"'record.c'\" \(4153 characters\)
- sed "s/^X//" >'record.c' <<'END_OF_FILE'
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <unistd.h>
- X#include <fcntl.h>
- X#include <time.h>
- X#include <string.h>
- X
- Xchar *ScoreF = SCORE_FILE;
- Xchar *LockF = LOCK_FILE;
- X
- X#define MAX_LINES 1003 /* no more than 1000 records */
- Xstatic char *(lines[MAX_LINES]);
- Xstatic int num_of_lines;
- X
- Xstatic void read_lines()
- X{
- X FILE *fp;
- X int c;
- X char x,buf[100];
- X fp=fopen(ScoreF,"r");
- X num_of_lines = c = 0;
- X while ((x=fgetc(fp)) != EOF) {
- X buf[c++] = x;
- X if (x == '\n') {
- X buf[c] = 0; lines[num_of_lines++] = strdup(buf);
- X c = 0;
- X if (num_of_lines >= MAX_LINES) break;
- X }
- X }
- X fclose(fp);
- X}
- X
- Xstatic int wrong_order(i,j) int i,j;
- X{
- X if (lines[i][12] < lines[j][12]) return 1;
- X if (lines[i][12] > lines[j][12]) return 0;
- X return (strcmp(lines[i]+19,lines[j]+19) > 0);
- X}
- X
- Xstatic void sort_lines()
- X{ int i,j,n;
- X char *p;
- X for (i=2,n=num_of_lines-1; i<n; i++)
- X for (j=i+1; j<num_of_lines; j++)
- X if (wrong_order(i,j)) {
- X p=lines[i]; lines[i]=lines[j]; lines[j]=p;
- X }
- X}
- X
- Xstatic void write_lines()
- X{
- X FILE *fp;
- X int i,n;
- X n = num_of_lines;
- X if (num_of_lines > (MAX_LINES - 1)) n = MAX_LINES - 1;
- X fp=fopen(ScoreF,"w");
- X for (i=0; i<n; i++) fprintf(fp,"%s",lines[i]);
- X fclose(fp);
- X for (i=0; i<num_of_lines; i++) free(lines[i]);
- X}
- X
- Xstatic void sort_record_file()
- X{
- X read_lines();
- X sort_lines();
- X write_lines();
- X}
- X
- Xstatic void lock_score_file()
- X{
- X while (open(LockF,O_CREAT|O_EXCL|O_RDWR) < 0) {
- X sleep(1); printf("Wait for updating the Make5 score file.\n");
- X }
- X chmod(LockF,0666); /* in case of aborted process */
- X}
- X
- Xstatic void two_digits(f,n) FILE *f; int n;
- X{
- X if (n > 9) fprintf(f,"%d",n);
- X else fprintf(f,"0%d",n);
- X}
- X
- Xstatic void update_score_file(name,level,step,seconds)
- X char *name;
- X int level, step, seconds;
- X{
- X time_t now;
- X struct tm *t;
- X int min,sec;
- X FILE *fp;
- X
- X now = time((time_t *)NULL);
- X t = localtime(&now);
- X min = seconds / 60;
- X sec = seconds % 60;
- X fp=fopen(ScoreF,"a");
- X fprintf(fp,"%-10s %d %3d %3d:",
- X name, level, step, min);
- X two_digits(fp,sec);
- X fprintf(fp," at ");
- X two_digits(fp,t->tm_hour); fputc(':',fp);
- X two_digits(fp,t->tm_min);
- X fprintf(fp," on ");
- X two_digits(fp,t->tm_mon+1); fputc('/',fp);
- X two_digits(fp,t->tm_mday); fputc('/',fp);
- X fprintf(fp,"%d\n",t->tm_year);
- X fclose(fp);
- X sort_record_file();
- X chmod(ScoreF,0644);
- X}
- X
- Xstatic void unlock_score_file()
- X{
- X remove(LockF);
- X}
- X
- Xvoid add_score_record(level,step,time)
- X int level,step,time;
- X{
- X lock_score_file();
- X update_score_file(getlogin(),level,step,time);
- X unlock_score_file();
- X}
- X
- Xstatic long int timer[2], last_timer[2];
- X
- Xvoid start_timer(n) int n;
- X{
- X last_timer[n] = time((time_t *)NULL);
- X}
- X
- Xvoid reset_timer(n) int n;
- X{
- X timer[n] = 0;
- X}
- X
- Xvoid pause_timer(n) int n;
- X{
- X timer[n] += (time((time_t *)NULL) - last_timer[n]);
- X}
- X
- Xint get_timer(n) int n;
- X{
- X return timer[n];
- X}
- X
- X#ifndef MAIL_COMMAND
- X#define MAIL_COMMAND "/usr/ucb/mail -s make5.record"
- X#endif
- X
- X#define x_row(x) (x / 21)
- X#define x_col(x) (x % 21)
- X
- Xvoid mail_record(current_level,num_moves,move_records)
- X int current_level,num_moves,move_records[];
- X{ int i;
- X char line[80], color[2];
- X char mail_command[6600]; /* more than enough for 180 steps */
- X
- X color[0]='X'; color[1]='O';
- X sprintf(line,"Challenge Level:%d Steps:%d Player:%s [%c]\n",
- X current_level, (num_moves+1)/2, getlogin(), color[1]);
- X sprintf(mail_command,"%s %s <<THE_END\n%s\n",
- X MAIL_COMMAND,getlogin(),line);
- X for (i=0; i<num_moves; i++) {
- X if (i & 1)
- X sprintf(line," [%c]:(%2d,%2d)\n",
- X color[1],
- X x_row(move_records[i]), x_col(move_records[i]));
- X else sprintf(line,"%2d [%c]:(%2d,%2d)",
- X i/2 + 1, color[0],
- X x_row(move_records[i]), x_col(move_records[i]));
- X strcat(mail_command,line);
- X }
- X strcat(mail_command,"\nTHE_END\n");
- X system(mail_command);
- X}
- END_OF_FILE
- if test 4153 -ne `wc -c <'record.c'`; then
- echo shar: \"'record.c'\" unpacked with wrong size!
- fi
- # end of 'record.c'
- fi
- if test -f 'select.C' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'select.C'\"
- else
- echo shar: Extracting \"'select.C'\" \(11252 characters\)
- sed "s/^X//" >'select.C' <<'END_OF_FILE'
- X// FILE: select.C (Ver. 1.1)
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X
- X#include "bdconst.h"
- X
- X//---------------------------------------------------------------------------
- X// For compatible with Pascal:
- X
- X#define maxint 32767
- X
- Xconst int start_pos = 22, end_pos = 418, center_point = 220;
- X
- X//---------------------------------------------------------------------------
- Xtypedef unsigned long pt_lev_set; // set of pt_lev_range
- X
- X#define B_1 01L
- X#define B_3 07L
- X#define B_4_6_8_10 01257L
- X#define B_4_6_8_10_12 05257L
- X#define B_5 037L
- X#define B_5_7_9_11_13 (B_4_6_8_10_12 << 1 + 1)
- X#define B_6_8_10 01277L
- X#define B_6_8_10_12 05277L
- X#define B_9 0777L
- X#define B_10 01777L
- X#define B_11 03777L
- X#define B_13 017777L
- X#define B_16 0177777L
- X#define B_18 0777777L
- X#define B_20 03777777L
- X#define B_21 07777777L
- X#define B_22 017777777L
- X#define B_23 037777777L
- X#define B_24 077777777L
- X#define B_25 0177777777L
- X#define B_26 0377777777L
- X#define B_27 0777777777L
- X
- Xconst pt_lev_set
- X alev[2][2][max_pt_lev+1] =
- X {{{0,B_1, B_3, B_3, B_5, B_10,B_10,B_10,B_11,B_11, // 0..9
- X B_16,B_16,B_16,B_16,B_16,B_16,B_16,B_18,B_18, // 10..18
- X B_20,B_20,B_21,B_22,B_23,B_24,B_25,B_26,B_27}, // alev[0][0]
- X {0,B_1, B_4_6_8_10_12, B_4_6_8_10_12,B_4_6_8_10_12,// 0..4
- X B_13,B_13,B_13,B_13,B_13,B_16,B_16,B_16,B_16, // 5..13
- X B_16,B_18,B_18,B_20,B_20,B_20,B_20,B_23,B_23, // 14..22
- X B_24,B_25,B_26,B_26,B_27}}, // alev[0][1]
- X {{0,0,B_1,B_1,B_1,B_4_6_8_10,B_9,B_9,B_9,B_9, // 0..9
- X B_13,B_13,B_13,B_13,B_16,B_16,B_16,B_16,B_16, // 10..18
- X B_16,B_16,B_20,B_20,B_20,B_22,B_23,B_25,B_26}, // alev[1][0]
- X {0,B_1,B_6_8_10,B_6_8_10,B_6_8_10,B_10,B_10,B_10, // 0..7
- X B_11,B_11,B_16,B_16,B_16,B_16,B_16,B_16,B_16, // 8..16
- X B_18,B_18,B_20,B_20,B_21,B_22,B_23,B_24,B_25, // 17..25
- X B_26,B_27}}}; // alev[1][1]
- X//---------------------------------------------------------------------------
- Xconst int
- X point5 = 1 , point44 = 3 , point43 = 4 , point33 = 5 , point3 = 13;
- X
- X// const pt_lev_set pointset4 = B_4_6_8_10_12;
- X // pointset3 = B_5_7_9_11_13;
- X // danger4 = B_6_8_10_12;
- X
- X//---------------------------------------------------------------------------
- Xconst int MAX_POINT = 100;
- X
- Xtypedef struct point_list_struct {
- X int n;
- X int x[MAX_POINT];
- X float v[MAX_POINT];
- X} point_list;
- X
- X//---------------------------------------------------------------------------
- X#include "debug.inc"
- X//---------------------------------------------------------------------------
- Xint max(int a, int b) { return ((a < b) ? b : a); }
- Xint min(int a, int b) { return ((a > b) ? b : a); }
- X//---------------------------------------------------------------------------
- Xconst float
- X pv_wet[max_pt_lev+1]
- X ={0, 20000,11000,10800,10400,10100, //0..5
- X 1,1,1,1,1,1,1,1, //6..13
- X 0.05,0.04,0.03,0.003,0.002,0.00021,0.00011, //14..20
- X 0.0000012,0.000001,0.0000001,0,0,0,0}; //21..27
- X//---------------------------------------------------------------------------
- Xfloat low_value(int p1, int p2) {
- X float v1=0, v2=0, w=0.9;
- X int i,k;
- X for (i=point33+1; i<=max_pt_lev; i++) {
- X if ((k=bdstatus.pt_lev_rec.pc[p1][i]) > 0) v1 += k * pv_wet[i];
- X if ((k=bdstatus.pt_lev_rec.pc[p2][i]) > 0) v2 += k * pv_wet[i] ;
- X }
- X return (v1 * w - v2 * (1.0 - w));
- X}
- X//---------------------------------------------------------------------------
- Xfloat value_of(int p1) {
- X int p2,i,k,n1,n2;
- X float v;
- X
- X p2 = 1 - p1;
- X n1 = bdstatus.pt_lev_rec.mp[p1];
- X n2 = bdstatus.pt_lev_rec.mp[p2];
- X if (n1 == point5) v = pv_wet[point5];
- X else if (bdstatus.pt_lev_rec.pc[p2][point5] > 1) v = -pv_wet[point5];
- X else if (n1 <= point33) v = pv_wet[n1];
- X else if (n2 <= point33) {
- X k = 0;
- X for (i=point5; i<=point33; i++)
- X k += bdstatus.pt_lev_rec.pc[p2][i];
- X switch (k) {
- X case 0: v = low_value(p1,p2); break;
- X case 1: v = (-7000 + low_value(p1,p2)); break;
- X default: v = (-8000 + low_value(p1,p2)); break;
- X }
- X }
- X else v = low_value(p1,p2);
- X return v;
- X}
- X//---------------------------------------------------------------------------
- Xvoid sort_list0(point_list &mp) {
- X float t;
- X int i,j,n,k;
- X n=mp.n-1;
- X for (i=0; i<n; i++) // sort mp.x[0..mp.n] by mp.v[0..mp.n]
- X for (j=i+1; j<=n; j++) {
- X if (mp.v[i] < mp.v[j]) {
- X k = mp.x[i]; mp.x[i] = mp.x[j]; mp.x[j] = k;
- X t = mp.v[i]; mp.v[i] = mp.v[j]; mp.v[j] = t;
- X }
- X }
- X}
- X//---------------------------------------------------------------------------
- X
- Xvoid sort_list1(point_list &mp, int p1) {
- X float t;
- X int p2,i,x;
- X update_record *z = new_update_record();
- X pt_lev_record *pt = new_pt_lev_record();
- X if (mp.n > 1) {
- X p2 = 1 - p1;
- X for (i=0; i<mp.n; i++) {
- X x = mp.x[i];
- X board[x] = player_color[p1];
- X update_board(1,x,z,pt);
- X mp.v[i] = t = -value_of(p2);
- X board[x] = blank;
- X restore(x,z,pt);
- X }
- X sort_list0(mp);
- X }
- X free(z); free(pt);
- X}
- X//---------------------------------------------------------------------------
- Xstatic const int
- X m_lev[max_pt_lev+1] =
- X {0,1,2,2,2,2,3,3,3,3,3,3,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5};
- X//---------------------------------------------------------------------------
- Xvoid sort_list2(point_list &mp, int p1) {
- X int p2,i,x;
- X
- X if (mp.n > 1) {
- X p2 = 1 - p1;
- X for (i=0; i<mp.n; i++) {
- X x = mp.x[i];
- X mp.v[i] = - ((bdstatus.point_lev[x][p1] << 5) -
- X bdstatus.point_lev[x][p2]);
- X }
- X sort_list0(mp);
- X }
- X}
- X//---------------------------------------------------------------------------
- X#define in_set(i,s) (s & (1L << (i-1)))
- X//---------------------------------------------------------------------------
- Xvoid add_point(int x, point_list &mp) {
- X if (mp.n < MAX_POINT) {
- X mp.x[mp.n] = x;
- X mp.v[mp.n] = 0;
- X (mp.n)++;
- X }
- X}
- X//---------------------------------------------------------------------------
- Xpoint_list &init_point_list(point_list &mp) {
- X mp.n=0; return mp;
- X}
- X//---------------------------------------------------------------------------
- Xvoid select_point(int p1, int depth, point_list &mp, int &m1, int &m2) {
- X pt_lev_set a00,a01,a10,a11;
- X int i,p2,l1,l2;
- X
- X p2 = 1 - p1;
- X m1 = bdstatus.pt_lev_rec.mp[p1];
- X m2 = bdstatus.pt_lev_rec.mp[p2];
- X a00 = alev[0][0][m1]; a01 = alev[0][1][m2];
- X a10 = alev[1][0][m1]; a11 = alev[1][1][m2];
- X for (i = start_pos; i <= end_pos; i++)
- X if (board[i] == blank) {
- X l1 = bdstatus.point_lev[i][p1];
- X l2 = bdstatus.point_lev[i][p2];
- X if ((in_set(l1,a00) && in_set(l1,a01)) ||
- X (in_set(l2,a10) && in_set(l2,a11)))
- X add_point(i,mp);
- X }
- X Check_No_Point("A",mp);
- X if ((depth == 1) && (step <= 3) && (step > 1))
- X sort_list1(mp,p1);
- X else sort_list2(mp,p1);
- X Check_No_Point("B",mp);
- X}
- X//---------------------------------------------------------------------------
- X#define with_danger_four(p) (bdstatus.pt_lev_rec.pc[p][4] \
- X + bdstatus.pt_lev_rec.pc[p][6] \
- X + bdstatus.pt_lev_rec.pc[p][8] \
- X + bdstatus.pt_lev_rec.pc[p][10])
- X//---------------------------------------------------------------------------
- Xfloat point_val(int x, int p1, int depth, float a) {
- X // using recursive alpha-beta prunning strategy
- X int i,p2,l1,l2,m1,m2;
- X float pv,m,t,a2;
- X point_list mp;
- X update_record *z = new_update_record();
- X pt_lev_record *pt = new_pt_lev_record();
- X
- X p2 = 1 - p1;
- X l1 = bdstatus.point_lev[x][p1];
- X l2 = bdstatus.point_lev[x][p2];
- X m = 0;
- X if (l1 == point5)
- X pv = maxint - depth;
- X else if (l1 <= point44)
- X pv = maxint - depth - 2;
- X else if ((l1 <= point33) && !with_danger_four(p2))
- X pv = maxint - depth - 4;
- X else {
- X int continue_search =
- X (depth <= min_depth) ||
- X (((l2 <= point33) || (l1 <= point33)) &&
- X ((depth < 9) || (depth <= max_depth)) ) ||
- X// (in_set(l1,danger4) && depth < 15) ||
- X ((l1 <= point3) && (depth <= max_depth));
- X board[x] = player_color[p1] ;
- X update_board(1,x,z,pt) ;
- X if (continue_search) {
- X select_point(p2,depth+1,init_point_list(mp),m2,m1) ;
- X m = 50000. ; i=0;
- X while ((i < mp.n) && (m > a))
- X {
- X if (m > 30000.)
- X a2 = -30000.0;
- X else a2 = -m;
- X t = -point_val(mp.x[i],p2,depth+1,a2);
- X if (t < m) m = t;
- X i++;
- X }
- X if (m != 0) pv = m;
- X else pv = -value_of(p2);
- X } else pv = -value_of(p2);
- X board[x] = blank ;
- X restore(x,z,pt) ;
- X }
- X free(z); free(pt);
- X return pv;
- X}
- X//---------------------------------------------------------------------------
- Xextern "C" int rand(void);
- Xint random_move(point_list &goodp) {
- X int i,j,n,k,x;
- X float mv;
- X mv = -50000.0; n=goodp.n;
- X for (i=0; i<n; i++) { // assume that n>0
- X if (goodp.v[i] > mv) {
- X mv=goodp.v[i]; k=1; x=goodp.x[i];
- X } else if (goodp.v[i] == mv) k++;
- X }
- X j = rand() % k;
- X for (i=0; i<n; i++)
- X if (goodp.v[i] == mv && j-- <= 0) return goodp.x[i];
- X return x;
- X}
- X//---------------------------------------------------------------------------
- Xint computer_select(int p, point_list &goodp) {
- X int m1,m2,i;
- X float m,t;
- X
- X if ((step == 1) && (p == 0)) return center_point;
- X // always start at the center position
- X select_point(p,1,init_point_list(goodp),m1,m2);
- X if (max_depth == 0) goodp.n = 1;
- X Check_No_Point("C",goodp);
- X if (goodp.n > 1) {
- X m = -30000.0; i = 0;
- X while ((i < goodp.n) && (m < 30000.0)) {
- X goodp.v[i] = t = point_val(goodp.x[i],p,1,m) ;
- X if (t > m) m = t ;
- X i++;
- X }
- X goodp.n = i;
- X }
- X Check_No_Point("D",goodp);
- X return random_move(goodp);
- X}
- X//---------------------------------------------------------------------------
- Xint num_of_suggestion, suggest_position[300];
- X//---------------------------------------------------------------------------
- Xextern "C" int computer_suggest(int p) {
- X int i,best;
- X point_list goodp;
- X
- X if ((step == 1) && (p == 0)) {
- X num_of_suggestion = 1;
- X suggest_position[0] = center_point;
- X return center_point;
- X }
- X best = computer_select(p,goodp);
- X num_of_suggestion = goodp.n;
- X for (i=0; i<num_of_suggestion; i++)
- X suggest_position[i] = goodp.x[i];
- X return best;
- X}
- X//---------------------------------------------------------------------------
- Xextern "C" int computer_move(int p) {
- X point_list goodp;
- X
- X return computer_select(p,goodp);
- X}
- X//---------------------------------------------------------------------------
- END_OF_FILE
- if test 11252 -ne `wc -c <'select.C'`; then
- echo shar: \"'select.C'\" unpacked with wrong size!
- fi
- # end of 'select.C'
- fi
- if test -f 'xmake5.6' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xmake5.6'\"
- else
- echo shar: Extracting \"'xmake5.6'\" \(2156 characters\)
- sed "s/^X//" >'xmake5.6' <<'END_OF_FILE'
- X.TH XMAKE5 6 "28 November 1991"
- X.SH NAME
- Xxmake5 \- the game of 5-in-a-row
- X.SH SYNOPSIS
- X.B xmake5
- X.SH DESCRIPTION
- X.I Make5
- Xis a game similar to Tic-Tac-Toe.
- XIt is called Wu3-Zi3-Qi2 in Chinese and is
- Xvery popular in the Far East.
- X5-in-a-row and Go-Moku are the other names
- Xfor this game.
- XYou may also find it called "Chess"
- Xon some Nitendo game cartridges.
- XI call it Make5 because the goal of this game
- Xis to make five continuous stones in a line.
- X.LP
- XThis game was originally played by two players
- Xon a board of infinite size. Each player puts
- Xa stone at one empty cross-point at a time.
- XThe winner is the one who first puts five
- Xcontinuous stones in a line, vertically,
- Xhorizontally, or diagonally.
- X.LP
- XHowever, this program plays the game on a finite
- Xboard the same size as a GO game board, which has
- X19 by 19 cross-points.
- X.I The only tricky rule
- X.I is that you must make
- X.I exactly five continuous
- X.I stones in a line to win.
- X.I Six or more stones in
- X.I a line do not count.
- X.LP
- XSome people play this game with a rule which
- Xprohibits the first player to make double-3 or
- Xdouble-4 attacking patterns. But I do not
- Xlike this rule and did not include it in this
- Xprogram.
- X.LP
- X.SH OPTIONS
- XThis program can play with you or play with itself.
- XYou can also play with your friends and use this
- Xprogram to update the board.
- XMost of the options in the "Setup..." menu can be
- Xchanged in the middle of a game. Hence, you can
- Xswitch the players, change the computer's searching
- Xlevel, or even undo your moves.
- XThe "Where..." menu provides hints for good
- Xpositions and the position of the last move.
- X.LP
- XYou can switch to the challenge mode, in which
- Xthe computer always moves first and you can not
- Xundo, change play level or order, or get suggestions
- Xfrom the computer. If you beat the computer, your
- Xname would be added into the list of winners.
- X.LP
- XHave fun!
- X
- X.SH BUGS
- X.nf
- XPlease send bugs to "hsiehch@cs.nyu.edu".
- X.LP
- XThis program does not have any learning ability.
- XYou could use the same strategy to beat it again and again.
- X.fi
- X.sp
- X.SH AUTHOR
- XChih-Hung Hsieh
- X.sp
- X.SH "SEE ALSO"
- Xcmake5 \- a simplified version that runs on ASCII terminals.
- X
- END_OF_FILE
- if test 2156 -ne `wc -c <'xmake5.6'`; then
- echo shar: \"'xmake5.6'\" unpacked with wrong size!
- fi
- # end of 'xmake5.6'
- fi
- if test -f 'xmake5.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xmake5.doc'\"
- else
- echo shar: Extracting \"'xmake5.doc'\" \(3823 characters\)
- sed "s/^X//" >'xmake5.doc' <<'END_OF_FILE'
- XName of the game:
- X=================
- X
- XMake5 is a game similar to Tic-Tac-Toe.
- XIt is called Wu3-Zi3-Qi2 in Chinese and is
- Xvery popular in the Far East. 5-in-a-row and
- XGo-Moku are the other names for this game.
- XYou may also find it called "Chess" on some
- XNitendo games. I call it Make5 because the goal
- Xof this game is to make five continuous stones
- Xin a line.
- X
- X
- XHow to play:
- X============
- X
- XThis game was originally played by two players
- Xon a board of infinite size. Each player puts
- Xa stone at one empty cross-point at a time.
- XThe winner is the one who first puts five
- Xcontinuous stones in a line, vertically,
- Xorizontally, or diagonally.
- X
- XHowever, this program plays the game on a finite
- Xboard the same size as a GO game board, which has
- X19 by 19 cross-points. The only tricky rule is
- Xthat you must make exactly five continuous stones
- Xin a line to win. Six or more stones in a line
- Xdo not count.
- X
- XSome people play this game with a rule which
- Xprohibits the first player to make double-3 or
- Xdouble-4 attacking patterns. But I do not
- Xlike this rule and did not include it in this
- Xprogram.
- X
- X
- XStrategies:
- X===========
- X
- XSo, you see why it is like Tic-Tac-Toe.
- XYou have to stop the other player's continuous
- Xlines of stones and design your own attacking lines.
- XUnlike Tic-Tac-Toe, this game is played on a large
- Xboard and requires five stones in a line to win.
- XIs there a winning strategy for the first player?
- XYou tell me.
- X
- X
- XOptions of playing:
- X===================
- X
- XThis program can play with you or play with itself.
- XYou can also play with your friends and use this
- Xprogram to update the board.
- X
- XMost of the options in the "Setup..." menu can be
- Xchanged in the middle of a game. Hence, you can
- Xswitch the players, change the computer's searching
- Xlevel, or even undo your moves.
- XThe "Where..." menu provides hints for good
- Xpositions and the position of the last move.
- X
- XYou can switch to the challenge mode, in which
- Xthe computer always moves first and you can not
- Xundo, change play level or order, or get suggestion
- Xfrom the computer. If you beat the computer, your
- Xname would be added into the list of winners.
- X
- XHave fun!
- X
- X
- XHistory of this program:
- X========================
- X
- XThe basic playing algorithm was designed in 1984
- Xas a term project of an A.I. class; it was written
- Xin Pascal and runs on Prime-750. The game was
- Xported to Turbo Pascal and ran on PC in 1986.
- X
- XNow this game is translated to C and C++ with an
- XX interface. Another version called cmake5 is also
- Xavailable. It uses the UNIX curses library and runs
- Xon most ASCII terminals.
- X
- X
- XChih-Hung Hsieh November 1991
- X
- X(Please send your comment to hsiehch@cs.nyu.edu.)
- X
- X
- X
- X Hsieh
- X------------------------
- X ,,, ||' ||'
- X '|| ,,|,,,| ||
- X,,,,|,|, || || ||
- X ||'''|| ,,,||,|
- X ,,,,|, ||,,,|| ||
- X || ||,, ||
- X '''''' || ,,||' ||
- X , '||'' ,|| | ||
- X ||''|| ,|'|| | ||
- X || || ,,'' || ||
- X || || || ||
- X ||'''' ''||' ''||'
- X------------------------
- X Chih
- X------------------------
- X ||'
- X || ,,
- X '''''''''''||'''''''''''
- X ||
- X || ,,
- X ''''''''''''''''''''
- X ,,
- X , ||' '|, ,,
- X | || '' '|,
- X ,|' || | '||
- X ,|| || |, ||'
- X '' '|||||||||||'
- X------------------------
- X Hung
- X------------------------
- X,,,,,,,,,|, ||,
- X ||' ||
- X || ||
- X|,,,,,,|| ,|'
- X|| '' ||
- X|| ||
- X||,,,,,,|, ||
- X'' ||' |' ',
- X || |' '|
- X ,|' ,' ,||
- X ,|' ,,|,,,|''' '||
- X'''|||' '''' ||
- X------------------------
- END_OF_FILE
- if test 3823 -ne `wc -c <'xmake5.doc'`; then
- echo shar: \"'xmake5.doc'\" unpacked with wrong size!
- fi
- # end of 'xmake5.doc'
- fi
- echo shar: End of archive 2 \(of 3\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-