Compare commits
5 Commits
697c6a8123
...
42f7a9e75a
Author | SHA1 | Date |
---|---|---|
|
42f7a9e75a | |
|
9ce465fc2e | |
|
f18025f359 | |
|
b7725e22ab | |
|
28941c7321 |
|
@ -0,0 +1,11 @@
|
|||
--indent=force-tab=8
|
||||
--style=attach
|
||||
--indent-after-parens
|
||||
--pad-comma
|
||||
--pad-header
|
||||
--fill-empty-lines
|
||||
--align-pointer=name
|
||||
--align-reference=name
|
||||
--attach-return-type
|
||||
--max-code-length=80
|
||||
--lineend=linux
|
|
@ -0,0 +1,3 @@
|
|||
((nil . ((c-basic-offset . 8)
|
||||
(indent-tabs-mode . t)
|
||||
(tab-width . 8))))
|
|
@ -1,2 +1,5 @@
|
|||
bin/*
|
||||
*/*.o
|
||||
*/*.fasl
|
||||
bf/*.bf
|
||||
*/*~
|
||||
|
|
|
@ -14,39 +14,39 @@ void Ackermann(mpz_t r, mpz_t m, mpz_t n) {
|
|||
mpz_addmul_ui(r, n, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
mpz_t t1, t2, ir;
|
||||
mpz_init(t1);
|
||||
mpz_sub_ui(t1, m, 1);
|
||||
mpz_init_set(t2, n);
|
||||
mpz_init_set_ui(ir, 1);
|
||||
|
||||
while(mpz_sgn(t2)>=0) {
|
||||
|
||||
while (mpz_sgn(t2)>=0) {
|
||||
Ackermann(r, t1, ir);
|
||||
mpz_set(ir, r);
|
||||
mpz_sub_ui(t2, t2, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
mpz_clear(t1);
|
||||
mpz_clear(t2);
|
||||
mpz_clear(ir);
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 3)
|
||||
return 1;
|
||||
mpz_t m, n, r;
|
||||
assert(!mpz_init_set_str(m, argv[1], 10));
|
||||
assert(!mpz_init_set_str(n, argv[2], 10));
|
||||
|
||||
|
||||
mpz_init(r);
|
||||
Ackermann(r, m, n);
|
||||
mpz_out_str(stdout, 10, r);
|
||||
putchar('\n');
|
||||
|
||||
|
||||
mpz_clear(m);
|
||||
mpz_clear(n);
|
||||
mpz_clear(r);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
;;;; This is a Common Lisp implementation of the Ackermann function
|
||||
|
||||
(declaim (ftype (function (fixnum integer) integer) Ackermann))
|
||||
|
||||
(defun Ackermann (m n)
|
||||
(declare (type fixnum m) (type integer n))
|
||||
(case m
|
||||
((0) (1+ n))
|
||||
((1) (+ 2 n))
|
||||
((2) (+ n n 3))
|
||||
((3) (+ (expt 2 (+ 3 n)) -3))
|
||||
(t (let ((ir 1) (m-1 (- m 1)))
|
||||
(dotimes (i (1+ n) ir)
|
||||
(setf ir (Ackermann m-1 ir)))))))
|
||||
|
||||
(defmacro Ackermann-test (m n)
|
||||
(let ((i (gensym)) (j (gensym)))
|
||||
`(dotimes (,i ,m nil) (dotimes (,j ,n) (format t "A(~d,~d)=~d~%" ,i ,j (Ackermann ,i ,j))))))
|
8
README
8
README
|
@ -5,6 +5,14 @@ The build.pl script is used to compile the programs.
|
|||
* If the names of the subdirectories are provided, then the script compiles the files in the given subdirectories of this repository if possible.
|
||||
* If only "clean" is provided, then the script cleans the bin/ directory and all object files.
|
||||
* If no argument is provided, then the script compiles everything in this repository that can be compiled.
|
||||
Additionally, these programs are used as references for this project:
|
||||
* C: GCC
|
||||
* Common Lisp: SBCL
|
||||
* Lua: LuaJIT
|
||||
|
||||
C coding style
|
||||
* The coding style should correspond to the coding style defined in the .astylerc file.
|
||||
* Long lines (>80 characters) should usually be broken in a way that makes sense to readers.
|
||||
|
||||
License
|
||||
The code here are licensed under GNU GPLv3 only. You may not choose a different license.
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
;;;; This is a simple BF-Common Lisp transpiler
|
||||
(defpackage :bf (:use :cl) (:export :tocl :tocl-string :tocl-file
|
||||
:tofile :tofile-string :tofile-file))
|
||||
(in-package :bf)
|
||||
|
||||
(defgeneric token-tocl (token &key list pointer input output &allow-other-keys))
|
||||
|
||||
(defstruct (operation)
|
||||
(optype nil :type (or null symbol)))
|
||||
|
||||
(defstruct (address)
|
||||
(absolute nil :type boolean)
|
||||
(offset 0 :type number))
|
||||
|
||||
(defmethod token-tocl ((token address) &key list pointer &allow-other-keys)
|
||||
(copy-list (if (address-absolute token)
|
||||
`(aref ,list ,(mod (address-offset token) 65536))
|
||||
(if (eql 0 (address-offset token))
|
||||
`(aref ,list ,pointer)
|
||||
`(aref ,list (mod (+ ,pointer ,(address-offset token)) 65536))))))
|
||||
|
||||
(defstruct (op-inc
|
||||
(:include operation (optype 'inc :type symbol :read-only t)))
|
||||
(position (make-address :absolute nil :offset 0) :type address)
|
||||
(delta 0 :type fixnum))
|
||||
|
||||
(defmethod token-tocl ((token op-inc) &key list pointer &allow-other-keys)
|
||||
(copy-list `(setf ,(token-tocl (op-inc-position token) :list list :pointer pointer)
|
||||
(mod (+ ,(token-tocl (op-inc-position token) :list list :pointer pointer)
|
||||
,(op-inc-delta token))
|
||||
256))))
|
||||
|
||||
(defstruct (op-offset
|
||||
(:include operation (optype 'offset :type symbol :read-only t)))
|
||||
(delta 0 :type fixnum))
|
||||
|
||||
(defmethod token-tocl ((token op-offset) &key pointer &allow-other-keys)
|
||||
(copy-list `(setf ,pointer (mod (+ ,pointer ,(op-offset-delta token)) 65536))))
|
||||
|
||||
(defstruct (op-read
|
||||
(:include operation (optype 'read :type symbol :read-only t)))
|
||||
(position (make-address :absolute nil :offset 0) :type address))
|
||||
|
||||
(defmethod token-tocl ((token op-read) &key list pointer input &allow-other-keys)
|
||||
(copy-list `(setf ,(token-tocl (op-read-position token) :list list :pointer pointer)
|
||||
(char-code (read-byte ,input nil #\Null)))))
|
||||
|
||||
(defstruct (op-write
|
||||
(:include operation (optype 'write :type symbol :read-only t)))
|
||||
(position (make-address :absolute nil :offset 0) :type address))
|
||||
|
||||
(defmethod token-tocl ((token op-write) &key list pointer output &allow-other-keys)
|
||||
(copy-list `(write-char
|
||||
(code-char ,(token-tocl (op-write-position token) :list list :pointer pointer))
|
||||
,output)))
|
||||
|
||||
(defstruct (op-loop
|
||||
(:include operation (optype 'loop :type symbol :read-only t)))
|
||||
(position (make-address :absolute nil :offset 0) :type address)
|
||||
(body nil :type list))
|
||||
|
||||
(defmethod token-tocl ((token op-loop) &key list pointer input output &allow-other-keys)
|
||||
(copy-list `(do () ((eql 0 ,(token-tocl (op-loop-position token)
|
||||
:list list
|
||||
:pointer pointer
|
||||
:input input
|
||||
:output output)))
|
||||
(progn . ,(transpile (op-loop-body token) list pointer input output t)))))
|
||||
|
||||
(defun tokenize-char (char &optional (stream *standard-input*) (recursive-p nil))
|
||||
(case char
|
||||
(#\+ (make-op-inc :delta 1))
|
||||
(#\- (make-op-inc :delta -1))
|
||||
(#\< (make-op-offset :delta -1))
|
||||
(#\> (make-op-offset :delta 1))
|
||||
(#\, (make-op-read))
|
||||
(#\. (make-op-write))
|
||||
(#\[ (make-op-loop :body (tokenize stream t)))
|
||||
(#\] (if recursive-p t (error "unbalanced ]")))
|
||||
(t nil)))
|
||||
|
||||
(defun tokenize (stream &optional (recursive-p nil))
|
||||
(do* ((c t (read-char stream nil))
|
||||
(v nil (tokenize-char c stream recursive-p))
|
||||
(l nil (if (typep v 'operation) (cons v l) l)))
|
||||
((or (null c) (eql t v)) l)))
|
||||
|
||||
(defmacro deref-pos (absolute-p offset)
|
||||
(let ((a (gensym)) (o (gensym)))
|
||||
`(copy (let ((,a ,absolute-p) (,o ,offset))
|
||||
(cond
|
||||
(,a (mod ,o 65536))
|
||||
((eql 0 ,o) 'pos)
|
||||
(t `(mod (+ pos ,,o) 65536)))))))
|
||||
|
||||
(defun let-wrapper (body list pointer input output)
|
||||
(declare (ignore input output))
|
||||
(copy-list `(let ((,list (make-array 65536 :element-type 'fixnum :initial-element 0
|
||||
:adjustable nil))
|
||||
(,pointer 0))
|
||||
(declare (type fixnum ,pointer))
|
||||
,@body)))
|
||||
|
||||
(defun transpile (elist list pointer input output &optional (recursive-p nil))
|
||||
(let ((l (nreverse (cons nil (loop for i in elist collect (token-tocl i
|
||||
:list list
|
||||
:pointer pointer
|
||||
:input input
|
||||
:output output))))))
|
||||
(if recursive-p l (let-wrapper l list pointer input output))))
|
||||
|
||||
(defun combine-tokens (elist)
|
||||
(do* ((r elist (cdr r)) (i (car r) (car r))) ((null i) elist)
|
||||
(typecase i
|
||||
(op-inc (loop for j on (cdr r) for e = (car j)
|
||||
while (and (typep e 'op-inc)
|
||||
(equalp (op-inc-position e) (op-inc-position i)))
|
||||
do (incf (op-inc-delta i) (op-inc-delta e))
|
||||
finally (setf (cdr r) j)))
|
||||
(op-offset (loop for j on (cdr r) for e = (car j)
|
||||
while (typep e 'op-offset)
|
||||
do (incf (op-offset-delta i) (op-offset-delta e))
|
||||
finally (setf (cdr r) j)))
|
||||
(op-loop (setf (op-loop-body i) (combine-tokens (op-loop-body i))))
|
||||
(t i))))
|
||||
|
||||
(defmacro optimize-token-list (elist)
|
||||
`(combine-tokens ,elist))
|
||||
|
||||
(defmacro toformlist (stream input output)
|
||||
`(transpile (optimize-token-list (tokenize ,stream)) (gensym) (gensym) ,input ,output))
|
||||
|
||||
(defmacro tocl (stream)
|
||||
`(compile nil `(lambda (&optional (is *standard-input*) (os *standard-output*))
|
||||
(declare (ignorable is os) (optimize speed))
|
||||
,(toformlist ,stream 'is 'os))))
|
||||
|
||||
(defmacro tocl-string (string)
|
||||
(let ((str (gensym)))
|
||||
`(with-input-from-string (,str ,string) (tocl ,str))))
|
||||
|
||||
(defmacro tocl-file (file)
|
||||
(let ((str (gensym)))
|
||||
`(with-open-file (,str ,file) (tocl ,str))))
|
||||
|
||||
(defmacro tofile (istream ostream)
|
||||
(let ((is (gensym)))
|
||||
`(let ((,is ,istream))
|
||||
(prin1 (toformlist ,is '*standard-input* '*standard-output*) ,ostream))))
|
||||
|
||||
(defmacro tofile-string (string ostream)
|
||||
(let ((str (gensym)))
|
||||
`(with-input-from-string (,str ,string) (tofile ,str ,ostream))))
|
||||
|
||||
(defmacro tofile-file (file ostream)
|
||||
(let ((str (gensym)))
|
||||
`(with-open-file (,str ,file) (tofile ,str ,ostream))))
|
|
@ -0,0 +1,253 @@
|
|||
local fn = tostring(arg[1]) or error("No filename supplied")
|
||||
local f = io.open(fn,"r") or error("Cannot open file")
|
||||
local str = f:read("*all")
|
||||
f:close()
|
||||
|
||||
local tokenize, t2str
|
||||
|
||||
local ops = {
|
||||
cval = 1, vset = 2, mpos = 3, writ = 4, wstr = 5, read = 6, loop = 7
|
||||
}
|
||||
|
||||
-- Matching patterns
|
||||
local ptns = {
|
||||
["^([%+%-]+)"] = function(_, str)
|
||||
local diff = 0
|
||||
for i = 1, #str do
|
||||
diff = diff + (string.sub(str,i,i) == "+" and 1 or -1)
|
||||
end
|
||||
return {ops.cval, diff}
|
||||
end,
|
||||
["^%[%-%]([%+%-]*)"] = function(_, str)
|
||||
local diff = 0
|
||||
for i = 1, #str do
|
||||
diff = diff + (string.sub(str,i,i) == "+" and 1 or -1)
|
||||
end
|
||||
return {ops.vset, diff}
|
||||
end,
|
||||
["^([<>]+)"] = function(_, str)
|
||||
local diff = 0
|
||||
for i = 1, #str do
|
||||
diff = diff + (string.sub(str,i,i) == "<" and -1 or 1)
|
||||
end
|
||||
return {ops.mpos, diff}
|
||||
end,
|
||||
["^(%.+)"] = function(_, str)
|
||||
return {ops.writ, string.len(str)}
|
||||
end,
|
||||
["^(,+)"] = function(_, str)
|
||||
return {ops.read, string.len(str)}
|
||||
end,
|
||||
["^(%b[])"] = function(_, str)
|
||||
return {ops.loop, tokenize(string.sub(str, 2, -2))}
|
||||
end,
|
||||
}
|
||||
|
||||
tokenize = function(str, pos, cont)
|
||||
if not pos then pos = 1 end
|
||||
local t = {}
|
||||
local endp = false
|
||||
while pos <= #str do
|
||||
if string.match(str, "^%s+$", pos) then break end
|
||||
local _, e = string.find(str, "^%s+", pos)
|
||||
if e then pos = e+1 end
|
||||
local tout = nil
|
||||
for p, f in pairs(ptns) do
|
||||
local match = {string.find(str, p, pos)}
|
||||
if match[1] then
|
||||
pos = match[2]+1
|
||||
match[2] = string.sub(str, pos+1) .. (cont or "")
|
||||
tout, endp = f(unpack(match, 2))
|
||||
break
|
||||
end
|
||||
end
|
||||
if not tout then
|
||||
return nil, (endp or "Invalid command: " .. string.sub(str, pos))
|
||||
end
|
||||
t[#t+1] = tout
|
||||
if endp then break end
|
||||
end
|
||||
return t, pos
|
||||
end
|
||||
|
||||
local function getbalance(t)
|
||||
local ct = {}
|
||||
local cl = {}
|
||||
local o = 0
|
||||
for i = 1, #t, 1 do
|
||||
local op = t[i][1]
|
||||
if op == ops.loop or op == ops.read or op == ops.writ or op == ops.vset then return nil end
|
||||
if op == ops.mpos then
|
||||
o = o + t[i][2]
|
||||
ct.min = ct.min and math.min(ct.min, o) or o
|
||||
ct.max = ct.max and math.max(ct.max, o) or o
|
||||
elseif op == ops.cval then
|
||||
if not ct[o] then
|
||||
ct[o] = {ops.cval, 0}
|
||||
cl[#cl+1] = o
|
||||
end
|
||||
ct[o][2] = ct[o][2] + t[i][2]
|
||||
end
|
||||
end
|
||||
table.sort(cl)
|
||||
return o == 0, ct, cl
|
||||
end
|
||||
|
||||
local function isbalanced(t)
|
||||
local o = 0
|
||||
for i = 1, #t, 1 do
|
||||
local op = t[i][1]
|
||||
if op == ops.loop or op == ops.read or op == ops.writ or op == ops.vset then return nil end
|
||||
if op == ops.mpos then o = o + t[i][2] end
|
||||
end
|
||||
return o == 0
|
||||
end
|
||||
|
||||
local function optimize(t)
|
||||
-- Pass 1: combine instructions
|
||||
local i = 1
|
||||
local j = 1
|
||||
local p1 = {}
|
||||
while (t[i]) do
|
||||
local op = t[i][1]
|
||||
p1[j] = {}
|
||||
for k, v in pairs(t[i]) do p1[j][k] = v end
|
||||
if op == ops.loop then
|
||||
p1[j][2] = optimize(p1[j][2])
|
||||
elseif op == ops.vset then
|
||||
while t[i+1] and t[i+1][1] == op do
|
||||
p1[j][2] = t[t+1][2]
|
||||
i = i+1
|
||||
end
|
||||
else
|
||||
while t[i+1] and t[i+1][1] == op do
|
||||
p1[j][2] = p1[j][2] + t[i+1][2]
|
||||
i = i+1
|
||||
end
|
||||
end
|
||||
i = i+1
|
||||
j = j+1
|
||||
end
|
||||
|
||||
-- Pass 2: compute constants
|
||||
local p2
|
||||
if t.st then
|
||||
local st = {}
|
||||
for i = 0, 32767 do st[i] = 0 end
|
||||
p2 = {}
|
||||
p2.st = st
|
||||
p2.p = 0
|
||||
local opt = true
|
||||
local j = 1
|
||||
local tbuf = ""
|
||||
for i = 1, #p1, 1 do
|
||||
if opt then
|
||||
local op = p1[i][1]
|
||||
if op == ops.mpos then
|
||||
p2.p = p2.p + p1[i][2]
|
||||
j = j-1
|
||||
elseif op == ops.cval then
|
||||
st[p2.p] = st[p2.p] + p1[i][2]
|
||||
j = j-1
|
||||
elseif op == ops.writ then
|
||||
tbuf = tbuf .. string.char(st[p2.p]):rep(p1[i][2])
|
||||
j = j-1
|
||||
elseif op == ops.vset then
|
||||
st[p2.p] = p1[i][2]
|
||||
j = j-1
|
||||
elseif op == ops.loop and isbalanced(p1[i][2]) then
|
||||
local _, ct, cl = getbalance(p1[i][2])
|
||||
local rep = nil
|
||||
if ct[0] then
|
||||
ct[0][2] = (-ct[0][2])%256
|
||||
for k = 0, 255 do
|
||||
if (st[p2.p]+256*k)%ct[0][2] == 0 then
|
||||
rep = k
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if rep then
|
||||
rep = (st[p2.p]+256*rep)/ct[0][2]
|
||||
ct[0][2] = -ct[0][2]
|
||||
for k = 1, #cl do
|
||||
local o = cl[k]
|
||||
local v = ct[o]
|
||||
local p = (p2.p+o)%32768
|
||||
st[p] = (st[p] + v[2]*rep)%256
|
||||
end
|
||||
else
|
||||
if #tbuf > 0 then
|
||||
p2[#p2+1] = {ops.wstr, tbuf}
|
||||
j = j+1
|
||||
end
|
||||
p2[j] = p1[i]
|
||||
return p2 -- Infinite loop
|
||||
end
|
||||
j = j-1
|
||||
else
|
||||
if #tbuf>0 then
|
||||
p2[j] = {ops.wstr,tbuf}
|
||||
tbuf = ""
|
||||
j = j+1
|
||||
end
|
||||
p2[j] = p1[i]
|
||||
opt = false
|
||||
end
|
||||
j = j+1
|
||||
else
|
||||
p2[j] = p1[i]
|
||||
j = j+1
|
||||
end
|
||||
end
|
||||
if #tbuf>0 then p2[#p2+1] = {ops.wstr, tbuf} end
|
||||
else
|
||||
p2 = p1
|
||||
end
|
||||
|
||||
-- Return result of final pass
|
||||
local t = p2
|
||||
return t
|
||||
end
|
||||
|
||||
local sct = {
|
||||
[ops.cval] = function(o) return string.format("tape[pos]=(tape[pos]%+d)%%256", o) end,
|
||||
[ops.vset] = function(v) return string.format("tape[pos]=%d", v%256) end,
|
||||
[ops.mpos] = function(o) return string.format("pos=(pos%+d)%%32768",o) end,
|
||||
[ops.writ] = function(n) return string.format("iowrite(srep(schar(tape[pos]),%d))", n) end,
|
||||
[ops.wstr] = function(s) return string.format("iowrite(%q)", s) end,
|
||||
[ops.read] = function(n) return string.format("tape[pos]=(string.byte(ioread(%d) or '',%d) or 0)", n, n) end,
|
||||
[ops.loop] = function(b) return string.format("while tape[pos]~=0 do\n%s\nend", t2str(b)) end,
|
||||
}
|
||||
|
||||
t2str = function(t)
|
||||
local r = {}
|
||||
for i = 1, #t do
|
||||
a = t[i]
|
||||
if not sct[a[1]] then error("Random transpiler bug: "..tostring(a[1])) end
|
||||
r[i] = sct[a[1]](unpack(a, 2))
|
||||
end
|
||||
return table.concat(r, "\n"), t.st and table.concat(t.st, ",", 0), t.p, nil
|
||||
end
|
||||
|
||||
local s, e = tokenize(str)
|
||||
if not s then error(e) end
|
||||
s.st = true
|
||||
|
||||
s, e = optimize(s)
|
||||
if not s then error(e) end
|
||||
|
||||
local c, p
|
||||
s, c, p, e = t2str(s)
|
||||
if not s then error(e) end
|
||||
|
||||
print(string.format([[
|
||||
local tape = {[0]=%s}
|
||||
local pos = %d
|
||||
local ioread = io.read
|
||||
local iowrite = io.write
|
||||
local sbyte = string.byte
|
||||
local schar = string.char
|
||||
local srep = string.rep
|
||||
%s
|
||||
]], c, p, s))
|
|
@ -35,9 +35,12 @@ static void gend() {
|
|||
|
||||
static void ginit() {
|
||||
S_ERRIF(SDL, SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO), gend());
|
||||
S_ERRIF(SDL, !(window = SDL_CreateWindow("Minesweeper", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 270, 300, 0)), gend());
|
||||
S_ERRIF(SDL, !(window = SDL_CreateWindow("Minesweeper",
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
270, 300, 0)), gend());
|
||||
windowid = SDL_GetWindowID(window);
|
||||
S_ERRIF(SDL, !(renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC)), gend());
|
||||
S_ERRIF(SDL, !(renderer = SDL_CreateRenderer(window, -1,
|
||||
SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC)), gend());
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
//int iiflags = IMG_INIT_PNG;
|
||||
|
@ -60,7 +63,9 @@ static void redraw_board() {
|
|||
int v;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
for (int j = 0; j < 9; j++) {
|
||||
r = (SDL_Rect){30*j, 30*i, 30, 30};
|
||||
r = (SDL_Rect) {
|
||||
30*j, 30*i, 30, 30
|
||||
};
|
||||
v = board[i][j];
|
||||
if (v&TILE_OPENED)
|
||||
v%=16;
|
||||
|
@ -72,10 +77,15 @@ static void redraw_board() {
|
|||
SDL_SetRenderDrawColor(renderer, 0xbb, 0xbb, 0xbb, 0xff);
|
||||
SDL_RenderDrawLine(renderer, 0, 270, 269, 270);
|
||||
SDL_RenderDrawLine(renderer, 0, 271, 269, 271);
|
||||
r = (SDL_Rect){0, 272, 270, 28};
|
||||
r = (SDL_Rect) {
|
||||
0, 272, 270, 28
|
||||
};
|
||||
SDL_SetRenderDrawColor(renderer, 0x7f, 0x7f, 0x7f, 0xff);
|
||||
SDL_RenderFillRect(renderer, &r);
|
||||
SDL_SetRenderDrawColor(renderer, endgame==2?0xff:0x00, endgame==1?0x80:0x00, endgame==0?0xff:0x00, 0xff);
|
||||
SDL_SetRenderDrawColor(renderer,
|
||||
endgame==2?0xff:0x00,
|
||||
endgame==1?0x80:0x00,
|
||||
endgame==0?0xff:0x00, 0xff);
|
||||
r.w = (uint16_t)270*nrevealed/(81-nmines);
|
||||
SDL_RenderFillRect(renderer, &r);
|
||||
SDL_RenderPresent(renderer);
|
||||
|
@ -133,7 +143,7 @@ static void newboard() {
|
|||
for (unsigned int i = 0; i < nmines; i++) {
|
||||
int x = rand()%9;
|
||||
int y = rand()%9;
|
||||
while(board[y][x] == 9||(x==0&&y==0)) {
|
||||
while (board[y][x] == 9||(x==0&&y==0)) {
|
||||
x--;
|
||||
if (x<0) {
|
||||
y = (y+8)%9;
|
||||
|
@ -157,55 +167,58 @@ static int mainloop() {
|
|||
SDL_PollEvent(&event);
|
||||
if (event.type == SDL_QUIT)
|
||||
return 0;
|
||||
switch(event.type) {
|
||||
case SDL_MOUSEBUTTONDOWN: {
|
||||
SDL_MouseButtonEvent mbevent = event.button;
|
||||
if (mbevent.clicks != 1)
|
||||
break;
|
||||
if (mbevent.windowID != windowid)
|
||||
break;
|
||||
if (mbevent.x < 0 || mbevent.x > 270)
|
||||
break;
|
||||
if ((nrevealed>0 || endgame) && mbevent.y >= 270 && mbevent.y < 300) {
|
||||
endgame = 0;
|
||||
newboard();
|
||||
break;
|
||||
}
|
||||
if (endgame)
|
||||
break;
|
||||
if (mbevent.y < 0 || mbevent.y >= 270)
|
||||
break;
|
||||
int x = mbevent.x/30;
|
||||
int y = mbevent.y/30;
|
||||
switch(mbevent.button) {
|
||||
case SDL_BUTTON_LEFT: {
|
||||
reveal_tile(x, y);
|
||||
break;
|
||||
}
|
||||
case SDL_BUTTON_RIGHT: {
|
||||
rmbevent(x, y);
|
||||
break;
|
||||
}
|
||||
case SDL_BUTTON_MIDDLE: {
|
||||
unflag_tile(x, y);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
switch (event.type) {
|
||||
case SDL_MOUSEBUTTONDOWN: {
|
||||
SDL_MouseButtonEvent mbevent = event.button;
|
||||
if (mbevent.clicks != 1)
|
||||
break;
|
||||
if (mbevent.windowID != windowid)
|
||||
break;
|
||||
if (mbevent.x < 0 || mbevent.x > 270)
|
||||
break;
|
||||
if ((nrevealed>0 || endgame) && mbevent.y >= 270 && mbevent.y < 300) {
|
||||
endgame = 0;
|
||||
newboard();
|
||||
break;
|
||||
}
|
||||
if (endgame)
|
||||
break;
|
||||
if (mbevent.y < 0 || mbevent.y >= 270)
|
||||
break;
|
||||
int x = mbevent.x/30;
|
||||
int y = mbevent.y/30;
|
||||
switch (mbevent.button) {
|
||||
case SDL_BUTTON_LEFT: {
|
||||
reveal_tile(x, y);
|
||||
break;
|
||||
}
|
||||
case SDL_BUTTON_RIGHT: {
|
||||
rmbevent(x, y);
|
||||
break;
|
||||
}
|
||||
case SDL_BUTTON_MIDDLE: {
|
||||
unflag_tile(x, y);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
redraw_board();
|
||||
break;
|
||||
};
|
||||
case SDL_WINDOWEVENT: {
|
||||
SDL_WindowEvent wevent = event.window;
|
||||
switch (wevent.event) {
|
||||
case SDL_WINDOWEVENT_EXPOSED: {
|
||||
redraw_board();
|
||||
break;
|
||||
};
|
||||
case SDL_WINDOWEVENT: {
|
||||
SDL_WindowEvent wevent = event.window;
|
||||
switch (wevent.event) {
|
||||
case SDL_WINDOWEVENT_EXPOSED:{
|
||||
redraw_board();
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SDL_Delay(10);
|
||||
return 1;
|
||||
|
@ -216,13 +229,13 @@ int main(int argc, char **argv) {
|
|||
nmines = strtoul(argv[1], NULL, 10);
|
||||
if (nmines < 9 || nmines > 72)
|
||||
nmines = 18;
|
||||
|
||||
|
||||
ginit();
|
||||
|
||||
srand(time(NULL));
|
||||
newboard();
|
||||
|
||||
while(mainloop());
|
||||
while (mainloop());
|
||||
gend();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue