betterchess

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

chess.ha (2168B)


      1 use io;
      2 use fmt;
      3 use ascii;
      4 
      5 export type invalidplace = !void;
      6 export type usedplace = !void;
      7 export type invalidmove = !void;
      8 export type empty = !void;
      9 
     10 export type ptype = enum rune {
     11 	KING = 'k',
     12 	QUEEN = 'q',
     13 	BISHOP = 'b',
     14 	KNIGHT = 'n',
     15 	ROOK = 'r',
     16 	PAWN = 'p'
     17 };
     18 
     19 export type color = enum {BLACK = 'b', WHITE = 'w'};
     20 export type movefn = *fn(_: piece, _: board, _: i64, _: i64) bool;
     21 
     22 export type piece = struct {
     23 	x: i64,
     24 	y: i64,
     25 	ty: ptype,
     26 	team: color,
     27 	valid: movefn,
     28 	moved: bool,
     29 	dead: bool
     30 };
     31 
     32 export type board = struct {
     33 	w: i64,
     34 	h: i64,
     35 	m: *map
     36 };
     37 
     38 export fn mkboard(w: i64, h: i64) board = board{w = w, h = h, m = mkmap((((w * h) / 4) * 3) : size)};
     39 
     40 export fn finish(b: *board) void = {
     41 	finishmap(b.m);
     42 };
     43 
     44 export fn mkpiece(b: *board, x: i64, y: i64, ty: ptype, team: color) (*piece | !invalidplace) = {
     45 	if (x < 0 || x >= b.w || y < 0 || y >= b.h) return invalidplace;
     46 
     47 	if (getpiece(b, x, y) is *piece) return usedplace;
     48 
     49 	let valid = switch(ty) {
     50 	case ptype::KING => yield &kingmove;
     51 	case ptype::QUEEN => yield &queenmove;
     52 	case ptype::BISHOP => yield &bishopmove;
     53 	case ptype::KNIGHT => yield &knightmove;
     54 	case ptype::ROOK => yield &rookmove;
     55 	case ptype::PAWN => yield &pawnmove;
     56 	};
     57 
     58 	addmap(b.m, x, y, alloc(piece{x = x, y = y, ty = ty, team = team, valid = valid, moved = false, dead = false})!: *piece);
     59 	return getmap(b.m, x, y)!;
     60 };
     61 
     62 export fn getpiece(b: *board, x: i64, y: i64) (*piece | !empty | !invalidplace) = {
     63 	if (x < 0 || x >= b.w || y < 0 || y >= b.h) return invalidplace;
     64 	return getmap(b.m, x, y);
     65 };
     66 
     67 export fn movepiece(b: *board, x1: i64, y1: i64, x2: i64, y2: i64) (void | !empty | !invalidmove | !invalidplace) = {
     68 	let p = getpiece(b, x1, y1)?;
     69 	if (!p.valid(*p, *b, x2, y2)) return invalidmove;
     70 
     71 	match (getpiece(b, x2, y2)) {
     72 	case let p: *piece => p.dead = true;
     73 	case => yield;
     74 	};
     75 
     76 	p.x = x2;
     77 	p.y = y2;
     78 	p.moved = true;
     79 };
     80 
     81 export fn print_board(b: board, f: io::handle) void = {
     82 	for (let ps .. b.m.1) {
     83 		for (let p .. ps) {
     84 			if (p.dead) continue;
     85 			let text = if (p.team == color::WHITE) ascii::toupper(p.ty: rune) else p.ty: rune;
     86 			fmt::fprintf(f, "{} {} {}\n", text, p.x, p.y)!;
     87 		};
     88 	};
     89 };