forsyth20121205-174063a80cc13 years agoHistory
718 lines · 14.0 KB · Brainfuck
RawDownload
implement Connect; ## Copyright © 2000 Vita Nuova Limited. All rights reserved.# include "sys.m";	sys: Sys;include "draw.m";	draw: Draw;	Point, Rect, Image, Font, Context, Screen, Display: import draw;include "tk.m";	tk: Tk;	Toplevel: import tk;include "tkclient.m";	tkclient: Tkclient;include "daytime.m";	daytime: Daytime;include "rand.m";	rand: Rand; # adtize and modularize stderr: ref Sys->FD; Connect: module {	init: fn(ctxt: ref Draw->Context, argv: list of string);}; nosleep, printout, auto: int;display: ref Draw->Display; init(ctxt: ref Draw->Context, argv: list of string){	sys = load Sys Sys->PATH;	draw = load Draw Draw->PATH;	tk = load Tk Tk->PATH;	tkclient = load Tkclient Tkclient->PATH;	daytime = load Daytime Daytime->PATH;	rand = load Rand Rand->PATH; 	argv = tl argv;	while(argv != nil){		s := hd argv;		if(s != nil && s[0] == '-'){			for(i := 1; i < len s; i++){				case s[i]{					'a' => auto = 1;					'p' => printout = 1;					's' => nosleep = 1;				}			}		}		argv = tl argv;	}	stderr = sys->fildes(2);	rand->init(daytime->now());	daytime = nil; 	if(ctxt == nil)		fatal("wm not running");	display = ctxt.display;	tkclient->init();	(win, wmcmd) := tkclient->toplevel(ctxt, "", "Connect", Tkclient->Resize | Tkclient->Hide);	mainwin = win;	sys->pctl(Sys->NEWPGRP, nil);	cmdch := chan of string;	tk->namechan(win, cmdch, "cmd");	for(i := 0; i < len win_config; i++)		cmd(win, win_config[i]);	pid := -1;	sync := chan of int;	mvch := chan of (int, int);	initboard();	setimage();	spawn game(sync, mvch);	pid = <- sync;	tkclient->onscreen(win, nil);	tkclient->startinput(win, "kbd"::"ptr"::nil); 	for(;;){		alt{			s := <-win.ctxt.kbd =>				tk->keyboard(win, s);			s := <-win.ctxt.ptr =>				tk->pointer(win, *s);			c := <-win.ctxt.ctl or			c = <-win.wreq or			c = <-wmcmd =>				case c{					"exit" =>						if(pid != -1)							kill(pid);						exit;					* =>						e := tkclient->wmctl(win, c);						if(e == nil && c[0] == '!'){							setimage();							drawboard();						}					}			c := <- cmdch =>				(nil, toks) := sys->tokenize(c, " ");				case hd toks{					"b1" or "b2" or "b3" =>						alt{							mvch <-= (int hd tl toks, int hd tl tl toks) => ;							* => ;						}					"bh" or "bm" or "wh" or "wm" =>						colour := BLACK;						knd := HUMAN;						if((hd toks)[0] == 'w')							colour = WHITE;						if((hd toks)[1] == 'm')							knd = MACHINE;						kind[colour] = knd;					"blev" or "wlev" =>						colour := BLACK;						e := "be";						if((hd toks)[0] == 'w'){							colour = WHITE;							e = "we";						}						sk := int cmd(win, ".f0." + e + " get");						if(sk > MAXPLIES)							sk = MAXPLIES;						if(sk >= 0)							skill[colour] = sk;					* =>						;				}			<- sync =>				pid = -1;				# exit;				spawn game(sync, mvch);				pid = <- sync;		}	}} WIDTH: con 400;HEIGHT: con 400; SZW: con 7;SZH: con 6;SZC: con 4;SZS: con 1024;PIECES: con SZW*SZH; BLACK, WHITE, EMPTY: con iota;MACHINE, HUMAN: con iota;SKILLB : con 8;SKILLW : con 0;MAXPLIES: con 10; board: array of array of int;	# for displaybrd: array of array of int;		# for calculationscol: array of int;pieces: array of int;val: array of int;kind: array of int;skill: array of int;name: array of string;lines: array of array of int;line: array of array of list of int; mainwin: ref Toplevel;brdimg: ref Image;brdr: Rect;brdx, brdy: int; black, white, bg: ref Image; movech: chan of (int, int); setimage(){	brdw := int tk->cmd(mainwin, ".p cget -actwidth");	brdh := int tk->cmd(mainwin, ".p cget -actheight");	brdr = Rect((0,0), (brdw, brdh));	brdimg = display.newimage(brdr, display.image.chans, 0, Draw->White);	if(brdimg == nil)		fatal("not enough image memory");	tk->putimage(mainwin, ".p", brdimg, nil);} game(sync: chan of int, mvch: chan of (int, int)){	sync <-= sys->pctl(0, nil);	movech = mvch;	initbrd();	play();	sync <-= 0;} initboard(){	i, j, k: int; 	board = array[SZW] of array of int;	brd = array[SZW] of array of int;	line = array[SZW] of array of list of int;	col = array[SZW] of int;	for(i = 0; i < SZW; i++){		board[i] = array[SZH] of int;		brd[i] = array[SZH] of int;		line[i] = array[SZH] of list of int;	}	pieces = array[2] of int;	val = array[2] of int;	kind = array[2] of int;	kind[BLACK] = MACHINE;	if(auto)		kind[WHITE] = MACHINE;	else		kind[WHITE] = HUMAN;	skill = array[2] of int;	skill[BLACK] = SKILLB;	skill[WHITE] = SKILLW;	name = array[2] of string;	name[BLACK] = "black";	name[WHITE] = "white";	black = display.color(Draw->Black);	white = display.color(Draw->White);	bg = display.color(Draw->Yellow);	n := SZW*(SZH-SZC+1)+SZH*(SZW-SZC+1)+2*(SZH-SZC+1)*(SZW-SZC+1);	lines = array[n] of array of int;	for(i = 0; i < n; i++)		lines[i] = array[2] of int;	m := 0;	for(i = 0; i < SZW; i++){		for(j = 0; j <= SZH-SZC; j++){			for(k = 0; k < SZC; k++){				line[i][j+k] = m :: line[i][j+k];			}			m++;		}	}	for(i = 0; i < SZH; i++){		for(j = 0; j <= SZW-SZC; j++){			for(k = 0; k < SZC; k++){				line[j+k][i] = m :: line[j+k][i];			}			m++;		}	}	for(i = 0; i <= SZW-SZC; i++){		for(j = 0; j <= SZH-SZC; j++){			for(k = 0; k < SZC; k++){				line[i+k][j+k] = m :: line[i+k][j+k];			}			m++;		}	}	for(i = 0; i <= SZW-SZC; i++){		for(j = 0; j <= SZH-SZC; j++){			for(k = 0; k < SZC; k++){				line[SZW-1-i-k][j+k] = m :: line[SZW-1-i-k][j+k];			}			m++;		}	}	if(m != n)		fatal(sys->sprint("%d != %d\n", m, n));		} initbrd(){	i, j: int; 	for(i = 0; i < SZW; i++){		col[i] = 0;		for(j = 0; j < SZH; j++)			board[i][j] = brd[i][j] = EMPTY;	}	pieces[BLACK] = pieces[WHITE] = 0;	val[BLACK] = val[WHITE] = 0;	drawboard();	n := len lines;	for(i = 0; i < n; i++)		lines[i][0] = lines[i][1] = 0;} plays := 0;bwins := 0;wwins := 0; play(){	if(plays&1)		(first, second) := (WHITE, BLACK);	else		(first, second) = (BLACK, WHITE);	for(;;){		if(pieces[BLACK]+pieces[WHITE] == PIECES)			break;		m1 := move(first, second);		if(printout)			sys->print("%s: %d %d %d\n", name[first], m1, val[BLACK], val[WHITE]);		if(win(first))			break;		if(pieces[BLACK]+pieces[WHITE] == PIECES)			break;		m2 := move(second, first);		if(printout)			sys->print("%s: %d %d %d\n", name[second], m2, val[BLACK], val[WHITE]);		if(win(second))			break;	}	if(win(BLACK)){		bwins++;		puts("black wins");		highlight(BLACK);	}	else if(win(WHITE)){		wwins++;		puts("white wins");		highlight(WHITE);	}	else		puts("draw");	sleep(2500);	plays++;	puts(sys->sprint("black %d:%d white", bwins, wwins));	sleep(2500);	if(printout)		sys->print("\n");} move(me: int, you: int): int{	if(kind[me] == MACHINE){		puts("machine " + name[me] + " move");		return genmove(me, you);	}	else{		m, n: int; 		# mvs := findmoves();		for(;;){			puts("human " + name[me] + " move");			m = getmove();			if(m < 0 || m >= SZW)				continue;			n = col[m];			valid := n >= 0 && n < SZH;			if(valid && brd[m][n] != EMPTY)				fatal("! EMPTY");			if(valid)				break;			puts("illegal move");			sleep(2500);		}		makemove(m, n, me, you, 0);		return m*SZS+n;	}} genmove(me: int, you: int): int{	m, n, v: int; 	mvs := findmoves();	if(skill[me] == 0){		l := len mvs;		r := rand->rand(l);		# r = 0;		while(--r >= 0)			mvs = tl mvs;		(m, n) = hd mvs;	}	else{		plies := skill[me];		left := PIECES-(pieces[BLACK]+pieces[WHITE]);		if(left < plies)		# limit search			plies = left;		else if(left < 2*plies)	# expand search to end			plies = left;		else{				# expand search nearer end of game			k := left/plies;			if(k < 3)				plies = ((k+2)*plies)/(k+1);		}		visits = leaves = 0;		(v, (m, n)) = minimax(me, you, plies, ∞);		if(0){			while(mvs != nil){				v0: int;				(a, b) := hd mvs;				makemove(a, b, me, you, 1);				(v0, (m, n)) = minimax(you, me, plies-1, ∞);				sys->print("	(%d, %d): %d\n", a, b, -v0);				undomove(a, b, me, you);				mvs = tl mvs;			}			sys->print("best move is %d, %d\n", m, n);			kind[WHITE] = HUMAN;		}		if(auto)					sys->print("eval = %d plies=%d goes=%d visits=%d\n", v, plies, len mvs, leaves);	}	makemove(m, n, me, you, 0);	return m*SZS+n;} findmoves(): list of (int, int){	mvs: list of (int, int); 	for(i := 0; i < SZW; i++){		if((j := col[i]) < SZH)			mvs = (i, j) :: mvs;	}	return mvs;} makemove(m: int, n: int, me: int, you: int, gen: int){	pieces[me]++;	brd[m][n] = me;	col[m]++;	for(l := line[m][n]; l != nil; l = tl l){		i := hd l;		a := lines[i][me];		b := lines[i][you];		lines[i][me]++;		if(a+b >= SZC)			fatal("makemove a+b");		if(b == 0){			val[me] += 2*a+1;			if(a == SZC-1)				val[me] += WIN;		}		else if(a == 0)			val[you] -= b*b;	}	if(!gen){		board[m][n] = me;		drawpiece(m, n, me);		panelupdate();		# sleep(1000);	}} undomove(m: int, n: int, me: int, you: int){	brd[m][n] = EMPTY;	pieces[me]--;	col[m]--;	for(l := line[m][n]; l != nil; l = tl l){		i := hd l;		a := lines[i][me];		b := lines[i][you];		lines[i][me]--;		if(a == 0 || a+b > SZC)			fatal("undomove a+b");		if(b == 0){			val[me] -= 2*a-1;			if(a == SZC)				val[me] -= WIN;		}		else if(a == 1)			val[you] += b*b;	}} win(me: int): int{	return val[me] > WIN/2;} highlight(me: int){	n := len lines;	for(i := 0; i < n; i++){		if(lines[i][me] == SZC){			for(j := 0; j < SZW; j++){				for(k := 0; k < SZH; k++){					for(l := line[j][k]; l != nil; l = tl l){						if(i == hd l)							highpiece(j, k, board[j][k]);					}				}			}		}	}} getmove(): int{	(x, nil) := <- movech;	return x/brdx;} drawboard(){	brdx = brdr.dx()/SZW;	brdy = brdr.dy()/SZH;

Lines 1–500 of 718.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t