initial commit

leesongun
Nov 2, 2022, 4:32 PM
W22NXX6SH6ZSON4SCYOOOPKW5WX3572DJDQ62QHF54MZXO27KTVAC

Dependencies

Change contents

  • file addition: src (d--r------)
    [2.1]
  • file addition: snake.zig (----------)
    [0.15]
    const io = @import("io.zig");
    const cursor = @import("cursor.zig");
    pub const init = io.init;
    var map = @import("map.zig"){};
    var fruit: @import("fruit.zig") = undefined;
    var head = cursor.init(0o40);
    var tail = cursor.init(0o40);
    pub fn main() void {
    fruit.seed(io.seed());
    newfruit().?;
    while (true) {
    io.print(head.pos, "<^>V"[head.dir]);
    io.sleep();
    const newdir = io.scandir(head.dir);
    io.print(head.pos, " lqml kxqk jmxj"[4 * @as(u4, newdir) + head.dir]);
    //push
    map.store(head, newdir);
    head.dir = newdir ^ 2;
    head.move() orelse break;
    if (head.pos != fruit.pos) {
    //pop
    map.load(&tail);
    map.zero(tail);
    //collision
    if (head.mask() & map.blank() == 0)
    break;
    //if (tail.index() != index(head))
    io.print(tail.pos, ' ');
    tail.move() orelse unreachable;
    } else newfruit() orelse break;
    }
    }
    fn newfruit() ?void {
    fruit.newfruit(map.blank() ^ cursor.mask(head)) orelse return null;
    io.print(fruit.pos, '*');
    }
  • file addition: map.zig (----------)
    [0.15]
    const Self = @This();
    const Cur = @import("cursor.zig").Self;
    pub fn blank(self: Self) u64 {
    return ~@reduce(.Or, self._);
    }
    pub fn zero(self: *Self, c: Cur) void {
    self._ &= @splat(2, ~c.mask());
    }
    pub fn store(self: *Self, c: Cur, dir: u2) void {
    const _m = @bitCast(@Vector(2, u1), dir ^ c.dir);
    self._ |= @as(@Vector(2, u64), _m) << @splat(2, c.pos);
    }
    pub fn load(self: Self, c: *Cur) void {
    const x = (self._ >> @splat(2, c.pos) & @splat(2, @as(u64, 1))) << .{ 0, 1 };
    c.dir ^= 2 ^ @intCast(u2, @reduce(.Or, x));
    }
    //change blank to 2
    _: @Vector(2, u64) = .{ 0, 0 },
  • file addition: main.zig (----------)
    [0.15]
    const std = @import("std");
    const os = std.os.linux;
    const handle = std.io.getStdIn().handle;
    const snake = @import("snake.zig");
    pub fn main() void {
    //hide cursor, clear screen, change chaeset, move cursor
    const init = "\x1B[?25l\x1B[2J\x1B(0\x1B[1;1H" ++ snake.init;
    _ = os.write(1, init, init.len);
    //move cursor, show cursor, change charset
    const deinit = "\x1B[11;1H\x1B[?25h\x1B(B";
    defer _ = os.write(1, deinit, deinit.len);
    const original_termios = rawmode();
    defer _ = os.tcsetattr(handle, .FLUSH, &original_termios);
    snake.main();
    }
    pub fn rawmode() os.termios {
    var termios: os.termios = undefined;
    _ = os.tcgetattr(handle, &termios);
    var original_termios = termios;
    // man 3 termios
    termios.iflag &= ~@as(os.tcflag_t, os.IGNBRK | os.BRKINT | os.PARMRK | os.ISTRIP | os.INLCR | os.IGNCR | os.ICRNL | os.IXON);
    termios.lflag &= ~@as(os.tcflag_t, os.ECHO | os.ECHONL | os.ICANON | os.ISIG | os.IEXTEN);
    termios.oflag &= ~@as(os.tcflag_t, os.OPOST);
    termios.cflag &= ~@as(os.tcflag_t, os.CSIZE | os.PARENB);
    termios.cflag |= os.CS8;
    termios.cc[6] = 0; // VMIN
    termios.cc[5] = 0; // VTIME
    _ = os.tcsetattr(handle, .FLUSH, &termios);
    return original_termios;
    }
    test {
    std.testing.refAllDecls(@This());
    }
  • file addition: io.zig (----------)
    [0.15]
    const os = @import("std").os.linux;
    pub const init = ("l" ++ "q" ** 8 ++ "k\n") ++ ("x\t x\n") ** 8 ++ ("m" ++ "q" ** 8 ++ "j");
    pub fn seed() u64 {
    var ret: u64 = undefined;
    const fd = @intCast(i32, os.open("/dev/urandom", os.O.RDONLY, undefined));
    _ = os.read(fd, @ptrCast([*]u8, &ret), 8);
    _ = os.close(fd);
    return ret;
    }
    pub fn scandir(curdir: u2) u2 {
    while (true) {
    var buff: [1]u8 = undefined;
    if (os.read(0, &buff, 1) == 0)
    return curdir ^ 2;
    var newdir: u2 = switch (buff[0]) {
    'D' => 2, // 'D', 'H', 'h', 'a' => 2,
    'C' => 0, // 'C', 'L', 'l', 'd' => 0,
    'B' => 1, // 'B', 'J', 'j', 's' => 1,
    'A' => 3, // 'A', 'K', 'k', 'w' => 3,
    else => continue,
    };
    if (newdir != curdir)
    return newdir;
    }
    }
    pub var printer = "\x1B[0;0H.".*;
    pub fn print(pos: u6, char: u8) void {
    printer["\x1B[".len] = @as(u8, '2') + (pos >> 3);
    printer["\x1B[0;".len] = @as(u8, '2') + (pos & 7);
    printer[printer.len - 1] = char;
    _ = os.write(1, &printer, printer.len);
    }
    const wait = os.timespec{ .tv_sec = 0, .tv_nsec = 1_5000_0000 };
    pub fn sleep() void {
    _ = os.nanosleep(&wait, null);
    }
    const printtype = enum {
    tail,
    neck,
    head,
    fruit,
    };
  • file addition: fruit.zig (----------)
    [0.15]
    // https://github.com/ziglang/zig/issues/2291
    // https://github.com/ziglang/zig/issues/1717
    extern fn @"llvm.x86.bmi.pdep.64"(u64, u64) u64;
    const Self = @This();
    const Rand = @import("std").rand.Sfc64;
    pos: u6,
    rand: Rand,
    pub fn seed(self: *Self, s: u64) void {
    self.rand = Rand.init(s);
    }
    pub fn newfruit(self: *Self, bb: u64) ?void {
    if (bb == 0) return null;
    const r = self.rand.random()
    .uintLessThanBiased(u6, @intCast(u6, @popCount(bb)));
    self.pos = @intCast(u6, @ctz(@"llvm.x86.bmi.pdep.64"(@as(u64, 1) << r, bb)));
    }
  • file addition: cursor.zig (----------)
    [0.15]
    pub usingnamespace packed struct(u8) {
    pos: u6 = 0o40,
    dir: u2 = 2,
    pub const Self = @This();
    fn to(self: Self) u8 {
    return @bitCast(u8, self);
    }
    pub fn move(self: *Self) ?void {
    const r = self.*;
    @ptrCast(*i8, self).* += switch (self.dir) {
    0 => -1,
    1 => -8,
    2 => 1,
    3 => 8,
    };
    if (@popCount(r.to() ^ self.to()) > 3) return null;
    }
    pub fn mask(self: Self) u64 {
    return @as(u64, 1) << self.pos;
    }
    pub fn init(c: u6) Self {
    return .{ .pos = c };
    }
    };