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 };