diff --git a/Makefile b/Makefile index 07b57931e26ed4883e783db35705dda3420d20d8..192293d25947d4da257d0b74c278eaf71cf7b531 100644 --- a/Makefile +++ b/Makefile @@ -60,6 +60,7 @@ TARGETS=\ gzip124 \ hiredis \ icpc \ + ioccc \ itc-benchmarks \ jsmn \ kgflags \ diff --git a/README.md b/README.md index 8c0c9e068d1dd50b386f7eac52747fc075dc3457..af8ae307a2007e43c60a545361b0a0347ac53aa4 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,8 @@ when available. We also summarize the license of each directory below. - `gzip124`: GPL - `hiredis`: Redis license (BSD-style), see `COPYING` - `icpc`: Unlicense +- `ioccc`: Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0), + see `COPYING` - `itc-benchmarks`: BSD 2-clause, see `COPYING` - `jsmn`: MIT - `kgflags`: MIT, see `LICENSE` diff --git a/ioccc/.frama-c/2020_burton_prog.eva/alarms.csv b/ioccc/.frama-c/2020_burton_prog.eva/alarms.csv new file mode 100644 index 0000000000000000000000000000000000000000..c1ac7e1a38f0738d8c0113923eb2949789aacc52 --- /dev/null +++ b/ioccc/.frama-c/2020_burton_prog.eva/alarms.csv @@ -0,0 +1,7 @@ +directory file line function property kind status property +2020/burton prog.c 1 main division_by_zero Unknown (long long)b ≢ 0 +2020/burton prog.c 1 main mem_access Unknown \valid_read(i) +2020/burton prog.c 1 main precondition of atoi Unknown valid_nptr: \valid_read(nptr) +2020/burton prog.c 1 main signed_overflow Unknown (long long)(a ^ (long long)(n / (long long)b)) * (long long)(y >> 0) ≤ 9223372036854775807 +2020/burton prog.c 1 main signed_overflow Unknown -9223372036854775808 ≤ (long long)(a ^ (long long)(n / (long long)b)) * (long long)(y >> 0) +FRAMAC_SHARE/libc stdlib.h 78 atoi precondition Unknown valid_nptr: \valid_read(nptr) diff --git a/ioccc/.frama-c/2020_burton_prog.eva/metrics.log b/ioccc/.frama-c/2020_burton_prog.eva/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..c77180949e684f1558c66ce564b8f6ac78da3e81 --- /dev/null +++ b/ioccc/.frama-c/2020_burton_prog.eva/metrics.log @@ -0,0 +1,9 @@ +[metrics] Eva coverage statistics +======================= +Syntactically reachable functions = 1 (out of 1) +Semantically reached functions = 1 +Coverage estimation = 100.0% +[metrics] Statements analyzed by Eva +-------------------------- +12 stmts in analyzed functions, 12 stmts analyzed (100.0%) +main: 12 stmts out of 12 (100.0%) diff --git a/ioccc/.frama-c/2020_burton_prog.eva/nonterm.log b/ioccc/.frama-c/2020_burton_prog.eva/nonterm.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_burton_prog.eva/warnings.log b/ioccc/.frama-c/2020_burton_prog.eva/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_burton_prog.parse/framac.ast b/ioccc/.frama-c/2020_burton_prog.parse/framac.ast new file mode 100644 index 0000000000000000000000000000000000000000..4635ab2bd466f46eda41638da934f93bb25b55e6 --- /dev/null +++ b/ioccc/.frama-c/2020_burton_prog.parse/framac.ast @@ -0,0 +1,38 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "stdarg.h" +#include "stdio.h" +#include "stdlib.h" +/*@ requires valid_read_string(format); + requires valid_read_nstring(param0, 8); + assigns \result, __fc_stdout->__fc_FILE_data; + assigns \result + \from (indirect: __fc_stdout->__fc_FILE_id), + (indirect: __fc_stdout->__fc_FILE_data), + (indirect: *(format + (0 ..))), (indirect: *(param0 + (0 ..))); + assigns __fc_stdout->__fc_FILE_data + \from (indirect: __fc_stdout->__fc_FILE_id), + __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), + *(param0 + (0 ..)); + */ +int printf_va_1(char const * __restrict format, char *param0); + +int main(int b, char **i) +{ + int __retres; + int tmp; + long long n = 6945503773712347754LL; + long long a = 5859838231191962459LL ^ n; + long long r = (a / (long long)b & a) >> 4; + i ++; + ; + tmp = atoi((char const *)*i); + long long y = (long long)tmp; + long long _ = + (((a ^ n / (long long)b) * (y >> 0) | (y >> 7)) & r) | (a ^ r); + printf("%.8s\n",(char *)(& _)); /* printf_va_1 */ + __retres = 0; + return __retres; +} + + diff --git a/ioccc/.frama-c/2020_burton_prog.parse/metrics.log b/ioccc/.frama-c/2020_burton_prog.parse/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..6ac96159f689f0a7944aeb0433d6767bc1c42322 --- /dev/null +++ b/ioccc/.frama-c/2020_burton_prog.parse/metrics.log @@ -0,0 +1,34 @@ +[metrics] Defined functions (1) +===================== + main (0 call); + +Specified-only functions (0) +============================ + + +Undefined and unspecified functions (0) +======================================= + + +'Extern' global variables (0) +============================= + + +Potential entry points (1) +========================== + main; + +Global metrics +============== +Sloc = 12 +Decision point = 0 +Global variables = 0 +If = 0 +Loop = 0 +Goto = 0 +Assignment = 8 +Exit point = 1 +Function = 1 +Function call = 2 +Pointer dereferencing = 1 +Cyclomatic complexity = 1 diff --git a/ioccc/.frama-c/2020_burton_prog.parse/warnings.log b/ioccc/.frama-c/2020_burton_prog.parse/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_giles_prog.eva/alarms.csv b/ioccc/.frama-c/2020_giles_prog.eva/alarms.csv new file mode 100644 index 0000000000000000000000000000000000000000..2eb94ea56836abedc468bc4264bf0e4fe2672010 --- /dev/null +++ b/ioccc/.frama-c/2020_giles_prog.eva/alarms.csv @@ -0,0 +1,220 @@ +directory file line function property kind status property +2020/giles prog.c 33 main signed_overflow Unknown -2147483648 ≤ m - 1 +2020/giles prog.c 39 main mem_access Unknown \valid_read(f) +2020/giles prog.c 39 main precondition of strlen Unknown valid_string_s: valid_read_string(s) +2020/giles prog.c 39 main precondition of fwrite Unknown valid_stream: \valid(stream) +2020/giles prog.c 42 main mem_access Unknown \valid_read(*f) +2020/giles prog.c 42 main mem_access Unknown \valid_read(tmp_5) +2020/giles prog.c 42 main precondition of strchr Unknown valid_string_s: valid_read_string(s) +2020/giles prog.c 42 main mem_access Unknown \valid(f) +2020/giles prog.c 45 main is_nan_or_infinite Unknown \is_finite(*(n_0 + 16)) +2020/giles prog.c 45 main is_nan_or_infinite Unknown \is_finite(*(n_0 + 16)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(b, e2), (double)49e2)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\add_double(x, \mul_double(\mul_double(b, e2), (double)49e2))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(b, e2), (double)49e2)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\add_double(x, \mul_double(\mul_double(b, e2), (double)49e2))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(b, e2), (double)49e2)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\add_double(x, \mul_double(\mul_double(b, e2), (double)49e2))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(b, e2), (double)49e2)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\add_double(x, \mul_double(\mul_double(b, e2), (double)49e2))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(b, e2), (double)49e2)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\add_double(x, \mul_double(\mul_double(b, e2), (double)49e2))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(b, e2), (double)49e2)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\add_double(x, \mul_double(\mul_double(b, e2), (double)49e2))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(b, e2), (double)49e2)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\add_double(x, \mul_double(\mul_double(b, e2), (double)49e2))) +2020/giles prog.c 46 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(b, e2), (double)49e2)) +2020/giles prog.c 47 main float_to_int Unknown -32769 < x +2020/giles prog.c 47 main float_to_int Unknown x < 32768 +2020/giles prog.c 50 main precondition of fread Unknown valid_stream: \valid(stream) +2020/giles prog.c 51 main precondition of memcmp Unknown initialization: s1: \initialized((char *)s1 + (0 .. n - 1)) +2020/giles prog.c 51 main precondition of memcmp Unknown initialization: s2: \initialized((char *)s2 + (0 .. n - 1)) +2020/giles prog.c 54 main initialization Unknown \initialized(&n) +2020/giles prog.c 54 main is_nan_or_infinite Unknown \is_finite(\div_double((double)16e3, (double)n)) +2020/giles prog.c 54 main float_to_int Unknown c < 4294967296 +2020/giles prog.c 54 main is_nan_or_infinite Unknown \is_finite(\div_double(c, (double)n)) +2020/giles prog.c 55 main initialization Unknown \initialized(&v) +2020/giles prog.c 57 main initialization Unknown \initialized(&e) +2020/giles prog.c 60 main initialization Unknown \initialized(&r) +2020/giles prog.c 61 main initialization Unknown \initialized(&k[(int)'Q']) +2020/giles prog.c 62 main is_nan_or_infinite Unknown \is_finite(\div_double(\mul_double(\sub_double(e2, g), (double)p), (double)n)) +2020/giles prog.c 62 main is_nan_or_infinite Unknown \is_finite(\add_double(d[(int)(0 + 2)], tmp_13)) +2020/giles prog.c 62 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(b, c), aa)) +2020/giles prog.c 62 main is_nan_or_infinite Unknown \is_finite(\add_double(d[(int)(1 + 2)], tmp_14)) +2020/giles prog.c 62 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(b, c), aa)) +2020/giles prog.c 62 main is_nan_or_infinite Unknown \is_finite(\add_double(d[(int)(2 + 2)], tmp_15)) +2020/giles prog.c 62 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(b, c), aa)) +2020/giles prog.c 62 main is_nan_or_infinite Unknown \is_finite(\add_double(i, c)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(*(&l[z] + 0), \mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 16)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 1)), *(&l[z] + 16))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(b, b), \mul_double(aa, aa))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(b, b)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(aa, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(*(&l[z] + 0), \mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 16)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 1)), *(&l[z] + 16))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(b, b), \mul_double(aa, aa))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(b, b)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(aa, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(x, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(*(&l[z] + 0), \mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 16)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 1)), *(&l[z] + 16))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(b, b), \mul_double(aa, aa))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(b, b)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(aa, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(x, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(*(&l[z] + 0), \mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 16)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 1)), *(&l[z] + 16))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(b, b), \mul_double(aa, aa))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(b, b)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(aa, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(x, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(*(&l[z] + 0), \mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 16)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 1)), *(&l[z] + 16))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(b, b), \mul_double(aa, aa))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(b, b)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(aa, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(x, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(*(&l[z] + 0), \mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 16)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 1)), *(&l[z] + 16))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(b, b), \mul_double(aa, aa))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(b, b)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(aa, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(x, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(*(&l[z] + 0), \mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 16)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 1)), *(&l[z] + 16))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(b, b), \mul_double(aa, aa))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(b, b)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(aa, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(x, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 17)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(\add_double(\mul_double(\sub_double((double)1, d[6]), d[2]), \mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))), \mul_double(*(&l[z] + 1), d[6]))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double((double)2, *(&l[z] + 17))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double((double)2, *(&l[z] + 17)), *(&l[z] + 0))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\sub_double(*(&l[z] + 0), \mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1)))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 17)), *(&l[z] + 1))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(*(&l[z] + 16)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(\mul_double(d[6], *(&l[z] + 1)), *(&l[z] + 16))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(\mul_double(b, b), \mul_double(aa, aa))) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(b, b)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\mul_double(aa, aa)) +2020/giles prog.c 63 main is_nan_or_infinite Unknown \is_finite(\add_double(x, aa)) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 68 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[z]) +2020/giles prog.c 70 main initialization Unknown \initialized(&k[(unsigned int)(z + 1)]) +FRAMAC_SHARE/libc stdio.h 352 fread precondition Unknown valid_stream: \valid(stream) +FRAMAC_SHARE/libc stdio.h 365 fwrite precondition Unknown valid_stream: \valid(stream) +FRAMAC_SHARE/libc string.h 57 memcmp precondition Unknown initialization: s1: \initialized((char *)s1 + (0 .. n - 1)) +FRAMAC_SHARE/libc string.h 58 memcmp precondition Unknown initialization: s2: \initialized((char *)s2 + (0 .. n - 1)) +FRAMAC_SHARE/libc string.h 125 strlen precondition Unknown valid_string_s: valid_read_string(s) +FRAMAC_SHARE/libc string.h 157 strchr precondition Unknown valid_string_s: valid_read_string(s) diff --git a/ioccc/.frama-c/2020_giles_prog.eva/metrics.log b/ioccc/.frama-c/2020_giles_prog.eva/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..26d803d8361e5c83bacb3d3dafe5b89bfcf74126 --- /dev/null +++ b/ioccc/.frama-c/2020_giles_prog.eva/metrics.log @@ -0,0 +1,11 @@ +[metrics] Eva coverage statistics +======================= +Syntactically reachable functions = 1 (out of 1) +Semantically reached functions = 1 +Coverage estimation = 100.0% +[metrics] References to non-analyzed functions +------------------------------------ +[metrics] Statements analyzed by Eva +-------------------------- +461 stmts in analyzed functions, 461 stmts analyzed (100.0%) +main: 461 stmts out of 461 (100.0%) diff --git a/ioccc/.frama-c/2020_giles_prog.eva/nonterm.log b/ioccc/.frama-c/2020_giles_prog.eva/nonterm.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_giles_prog.eva/warnings.log b/ioccc/.frama-c/2020_giles_prog.eva/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_giles_prog.parse/framac.ast b/ioccc/.frama-c/2020_giles_prog.parse/framac.ast new file mode 100644 index 0000000000000000000000000000000000000000..5d048c9cd3322e1a45311fa448e0727af761d769 --- /dev/null +++ b/ioccc/.frama-c/2020_giles_prog.parse/framac.ast @@ -0,0 +1,580 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "stdarg.h" +#include "stddef.h" +#include "stdint.h" +#include "stdio.h" +#include "string.h" +#include "strings.h" +char const *t = + "Dual-tone multi-frequency signaling(DTMF) is a telecommunication signalingsystem using the voice-frequency bandInvalid WAV input\000Read error\000Cannot read dtmf.bin\000rb\000" + 111; +/*@ requires valid_read_string(format); + requires valid_read_string(param0); + assigns \result, stream->__fc_FILE_data; + assigns \result + \from (indirect: stream->__fc_FILE_id), + (indirect: stream->__fc_FILE_data), + (indirect: *(format + (0 ..))), (indirect: *(param0 + (0 ..))); + assigns stream->__fc_FILE_data + \from (indirect: stream->__fc_FILE_id), stream->__fc_FILE_data, + (indirect: *(format + (0 ..))), *(param0 + (0 ..)); + */ +int fprintf_va_1(FILE * __restrict stream, char const * __restrict format, + char *param0); + +/*@ requires valid_read_string(format); + requires valid_read_string(param0); + assigns \result, stream->__fc_FILE_data; + assigns \result + \from (indirect: stream->__fc_FILE_id), + (indirect: stream->__fc_FILE_data), + (indirect: *(format + (0 ..))), (indirect: *(param0 + (0 ..))); + assigns stream->__fc_FILE_data + \from (indirect: stream->__fc_FILE_id), stream->__fc_FILE_data, + (indirect: *(format + (0 ..))), *(param0 + (0 ..)); + */ +int fprintf_va_2(FILE * __restrict stream, char const * __restrict format, + char *param0); + +/*@ requires valid_read_string(format); + requires valid_read_string(param0); + assigns \result, stream->__fc_FILE_data; + assigns \result + \from (indirect: stream->__fc_FILE_id), + (indirect: stream->__fc_FILE_data), + (indirect: *(format + (0 ..))), (indirect: *(param0 + (0 ..))); + assigns stream->__fc_FILE_data + \from (indirect: stream->__fc_FILE_id), stream->__fc_FILE_data, + (indirect: *(format + (0 ..))), *(param0 + (0 ..)); + */ +int fprintf_va_3(FILE * __restrict stream, char const * __restrict format, + char *param0); + +int main(int m, char **f) +{ + int __retres; + double aa; + double c; + double tmp; + double g; + double b; + double x; + char k[':' + 's']; + FILE *h; + int tmp_3; + size_t tmp_0; + uint32_t o[2]; + uint32_t z; + uint32_t n; + uint16_t e; + uint16_t v; + int16_t r; + m --; + if (m) tmp = (double)1; else tmp = 0.994; + double d[8] = {[6] = tmp, 1e-4}; + double i = (double)0; + double l['0'] = {(double)0}; + double e2 = (double)0; + h = fopen(t + ')',t + '2'); + if (! h) { + memcpy: + fprintf(__fc_stderr,"%s\n",(char *)((t + 'A') - '$')); /* fprintf_va_1 */ + __retres = 1; + goto return_label; + } + tmp_0 = fread((void *)(& k['U']),(unsigned long)',',(unsigned long)1,h); + if (tmp_0) { + size_t tmp_1; + tmp_1 = fread((void *)(& l[16]),(unsigned long)('C' + '='), + (unsigned long)1,h); + if (tmp_1) { + size_t tmp_2; + tmp_2 = fread((void *)(k),(unsigned long)'Q',(unsigned long)1,h); + if (tmp_2) tmp_3 = 0; else tmp_3 = 1; + } + else tmp_3 = 1; + } + else tmp_3 = 1; + uint32_t p = (unsigned int)tmp_3; + uint32_t w = (unsigned int)0; + fclose(h); + if (p) goto memcpy; + if (m) h = __fc_stdout; else h = __fc_stdin; + setvbuf(h,(char *)0,0,(unsigned long)65536); + if (m) { + size_t tmp_4; + f ++; + ; + tmp_4 = strlen((char const *)*f); + z = (unsigned int)((size_t)6400 * tmp_4); + z = z; + memcpy((void *)(& k['+'] + 'R'),(void const *)(& z),(unsigned long)4); + z += (uint32_t)'$'; + memcpy((void *)(& k['Y']),(void const *)(& z),(unsigned long)4); + fwrite((void const *)(& k['U']),(unsigned long)',',(unsigned long)1,h); + while (*(*f)) { + char *tmp_6; + char *tmp_5; + tmp_5 = *f; + (*f) ++; + ; + tmp_6 = strchr((char const *)(k),(int)*tmp_5); + char *c_0 = tmp_6; + memset((void *)(l),0,(unsigned long)('F' + ':')); + if (c_0) { + w = (unsigned int)(c_0 - k); + double *n_0 = & l[(w % (unsigned int)4) * (unsigned int)2]; + *n_0 = *(n_0 + 16); + n_0 = & l[8] + ((w / (uint32_t)4) % (unsigned int)4) * (unsigned int)2; + *n_0 = *(n_0 + 16); + } + w = (unsigned int)3200; + while (w) { + { + int tmp_7; + x = (double)0; + z = (unsigned int)2; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + x += (b * e2) * 49e2; + z = (unsigned int)10; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + x += (b * e2) * 49e2; + z = (unsigned int)6; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + x += (b * e2) * 49e2; + z = (unsigned int)12; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + x += (b * e2) * 49e2; + z = (unsigned int)4; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + x += (b * e2) * 49e2; + z = (unsigned int)8; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + x += (b * e2) * 49e2; + z = (unsigned int)14; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + x += (b * e2) * 49e2; + z = (unsigned int)0; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + x += (b * e2) * 49e2; + r = (short)x; + fwrite((void const *)(& r),(unsigned long)2,(unsigned long)1,h); + if (w > (uint32_t)1300) tmp_7 = 1; else tmp_7 = -1; + e2 += (double)tmp_7 * 3e-2; + if (e2 > (double)1) e2 = (double)1; + else { + double tmp_8; + if (e2 > (double)0) tmp_8 = e2; else tmp_8 = (double)0; + e2 = tmp_8; + } + } + w -= (uint32_t)1; + } + } + } + else { + size_t tmp_9; + int tmp_10; + int tmp_17; + tmp_9 = fread((void *)(& k['+'] + 'V'),(unsigned long)',', + (unsigned long)1,h); + if (! tmp_9) { + fread: fprintf(__fc_stderr,"%s\n",(char *)(t + 18)); /* fprintf_va_2 */ + __retres = 1; + goto return_label; + } + tmp_10 = memcmp((void const *)(& k['+'] + '^'),(void const *)(& k[']']), + (unsigned long)14); + if (tmp_10) { + int_16t: fprintf(__fc_stderr,"%s\n",(char *)t); /* fprintf_va_3 */ + __retres = 1; + goto return_label; + } + memcpy((void *)(& n),(void const *)(& k['+'] + 'n'),(unsigned long)4); + c = 16e3 / (double)n; + n = (unsigned int)c; + if ((double)n != c) n += (uint32_t)1; + c /= (double)n; + memcpy((void *)(& v),(void const *)(& k[43] + 'x'),(unsigned long)2); + v = (unsigned short)((int)v / 8); + memcpy((void *)(& e),(void const *)(& k['+'] + 'v'),(unsigned long)2); + if (! e) goto int_16t; + else + if (! v) goto int_16t; + else + if ((int)v > 4) goto int_16t; + e = (unsigned short)((int)e - (int)v); + while (1) { + size_t tmp_16; + tmp_16 = fread((void *)(& k['Q']),(unsigned long)v,(unsigned long)1,h); + if (! tmp_16) break; + z = (unsigned int)e; + z = z; + while (1) { + uint32_t tmp_11; + tmp_11 = z; + z -= (uint32_t)1; + ; + if (tmp_11) { + int tmp_12; + tmp_12 = getc(h); + if (! (tmp_12 >= 0)) break; + } + else break; + } + if ((int)v > 1) { + memcpy((void *)(& r),(void const *)(& k[v] + 'O'),(unsigned long)2); + g = ((double)r / 512.0) / (double)'@'; + } + else g = (double)((unsigned char)k['Q']) / 128.0 - (double)1; + p = n; + while (p) { + { + double tmp_13; + double tmp_14; + double tmp_15; + aa = ((e2 - g) * (double)p) / (double)n + g; + b = (double)0 - i; + if (b < (double)0) b = (double)1 + b; else b = (double)1 - b; + if (b > (double)0) tmp_13 = (b * c) * aa; else tmp_13 = (double)0; + d[0 + 2] += tmp_13; + b = (double)1 - i; + if (b < (double)0) b = (double)1 + b; else b = (double)1 - b; + if (b > (double)0) tmp_14 = (b * c) * aa; else tmp_14 = (double)0; + d[1 + 2] += tmp_14; + b = (double)2 - i; + if (b < (double)0) b = (double)1 + b; else b = (double)1 - b; + if (b > (double)0) tmp_15 = (b * c) * aa; else tmp_15 = (double)0; + d[2 + 2] += tmp_15; + i += c; + if (i >= (double)1) { + memset((void *)(d),0,(unsigned long)16); + memset((void *)(o),0,(unsigned long)8); + x = (double)0; + z = (unsigned int)2; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + b = *(& l[z] + 0) - (d[6] * *(& l[z] + 17)) * *(& l[z] + 1); + aa = (d[6] * *(& l[z] + 1)) * *(& l[z] + 16); + aa = b * b + aa * aa; + x += aa; + if (aa >= d[z / (uint32_t)8]) { + o[z / (uint32_t)8] = z / (uint32_t)2; + d[z / (uint32_t)8] = aa; + } + z = (unsigned int)10; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + b = *(& l[z] + 0) - (d[6] * *(& l[z] + 17)) * *(& l[z] + 1); + aa = (d[6] * *(& l[z] + 1)) * *(& l[z] + 16); + aa = b * b + aa * aa; + x += aa; + if (aa >= d[z / (uint32_t)8]) { + o[z / (uint32_t)8] = z / (uint32_t)2; + d[z / (uint32_t)8] = aa; + } + z = (unsigned int)6; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + b = *(& l[z] + 0) - (d[6] * *(& l[z] + 17)) * *(& l[z] + 1); + aa = (d[6] * *(& l[z] + 1)) * *(& l[z] + 16); + aa = b * b + aa * aa; + x += aa; + if (aa >= d[z / (uint32_t)8]) { + o[z / (uint32_t)8] = z / (uint32_t)2; + d[z / (uint32_t)8] = aa; + } + z = (unsigned int)12; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + b = *(& l[z] + 0) - (d[6] * *(& l[z] + 17)) * *(& l[z] + 1); + aa = (d[6] * *(& l[z] + 1)) * *(& l[z] + 16); + aa = b * b + aa * aa; + x += aa; + if (aa >= d[z / (uint32_t)8]) { + o[z / (uint32_t)8] = z / (uint32_t)2; + d[z / (uint32_t)8] = aa; + } + z = (unsigned int)4; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + b = *(& l[z] + 0) - (d[6] * *(& l[z] + 17)) * *(& l[z] + 1); + aa = (d[6] * *(& l[z] + 1)) * *(& l[z] + 16); + aa = b * b + aa * aa; + x += aa; + if (aa >= d[z / (uint32_t)8]) { + o[z / (uint32_t)8] = z / (uint32_t)2; + d[z / (uint32_t)8] = aa; + } + z = (unsigned int)8; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + b = *(& l[z] + 0) - (d[6] * *(& l[z] + 17)) * *(& l[z] + 1); + aa = (d[6] * *(& l[z] + 1)) * *(& l[z] + 16); + aa = b * b + aa * aa; + x += aa; + if (aa >= d[z / (uint32_t)8]) { + o[z / (uint32_t)8] = z / (uint32_t)2; + d[z / (uint32_t)8] = aa; + } + z = (unsigned int)14; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + b = *(& l[z] + 0) - (d[6] * *(& l[z] + 17)) * *(& l[z] + 1); + aa = (d[6] * *(& l[z] + 1)) * *(& l[z] + 16); + aa = b * b + aa * aa; + x += aa; + if (aa >= d[z / (uint32_t)8]) { + o[z / (uint32_t)8] = z / (uint32_t)2; + d[z / (uint32_t)8] = aa; + } + z = (unsigned int)0; + b = (((double)1 - d[6]) * d[2] + ((double)2 * *(& l[z] + 17)) * *( + & l[z] + 0)) - *(& l[z] + 1) * d[6]; + *(& l[z] + 1) = *(& l[z] + 0); + *(& l[z] + 0) = b * d[6]; + b = *(& l[z] + 0) - (d[6] * *(& l[z] + 17)) * *(& l[z] + 1); + aa = (d[6] * *(& l[z] + 1)) * *(& l[z] + 16); + aa = b * b + aa * aa; + x += aa; + if (aa >= d[z / (uint32_t)8]) { + o[z / (uint32_t)8] = z / (uint32_t)2; + d[z / (uint32_t)8] = aa; + } + if (w) r = (short)(x > d[7] * 0.45); + else r = (short)(x > d[7] * 0.6); + if (r) { + if (! w) memset((void *)(& l[32]),0,(unsigned long)128); + if (x > d[7]) d[7] = x; + l[((uint32_t)16 + o[1] * (uint32_t)4) + o[0]] += (double)1; + } + else + if (w) { + b = (double)(-1); + char j = (char)0; + x = (double)0; + z = (unsigned int)2; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j = k[z + (uint32_t)1]; + } + z = (unsigned int)10; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j = k[z + (uint32_t)1]; + } + z = (unsigned int)6; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j = k[z + (uint32_t)1]; + } + z = (unsigned int)12; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j = k[z + (uint32_t)1]; + } + z = (unsigned int)4; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j = k[z + (uint32_t)1]; + } + z = (unsigned int)8; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j = k[z + (uint32_t)1]; + } + z = (unsigned int)14; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j = k[z + (uint32_t)1]; + } + z = (unsigned int)0; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j = k[z + (uint32_t)1]; + } + putchar((int)j); + } + w = (unsigned int)r; + memmove((void *)(& d[2]),(void const *)(& d[3]), + (unsigned long)24); + i -= (double)1; + } + } + p -= (uint32_t)1; + } + e2 = g; + } + tmp_17 = ferror(h); + if (tmp_17) goto fread; + if (w) { + b = (double)(-1); + char j_0 = (char)0; + x = (double)0; + z = (unsigned int)2; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j_0 = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j_0 = k[z + (uint32_t)1]; + } + z = (unsigned int)10; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j_0 = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j_0 = k[z + (uint32_t)1]; + } + z = (unsigned int)6; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j_0 = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j_0 = k[z + (uint32_t)1]; + } + z = (unsigned int)12; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j_0 = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j_0 = k[z + (uint32_t)1]; + } + z = (unsigned int)4; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j_0 = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j_0 = k[z + (uint32_t)1]; + } + z = (unsigned int)8; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j_0 = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j_0 = k[z + (uint32_t)1]; + } + z = (unsigned int)14; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j_0 = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j_0 = k[z + (uint32_t)1]; + } + z = (unsigned int)0; + z = z; + if (*(& l[z] + 32) > b) { + b = *(& l[z] + 32); + j_0 = k[z]; + } + if (*(& l[z] + 33) > b) { + b = *(& l[z] + 33); + j_0 = k[z + (uint32_t)1]; + } + putchar((int)j_0); + } + puts("0123456789" + 10); + } + __retres = 0; + return_label: return __retres; +} + + diff --git a/ioccc/.frama-c/2020_giles_prog.parse/metrics.log b/ioccc/.frama-c/2020_giles_prog.parse/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..0b1f1b17a0aa3a98192ed930966faeaad7cdeed7 --- /dev/null +++ b/ioccc/.frama-c/2020_giles_prog.parse/metrics.log @@ -0,0 +1,34 @@ +[metrics] Defined functions (1) +===================== + main (0 call); + +Specified-only functions (0) +============================ + + +Undefined and unspecified functions (0) +======================================= + + +'Extern' global variables (0) +============================= + + +Potential entry points (1) +========================== + main; + +Global metrics +============== +Sloc = 461 +Decision point = 79 +Global variables = 1 +If = 79 +Loop = 5 +Goto = 8 +Assignment = 317 +Exit point = 1 +Function = 1 +Function call = 32 +Pointer dereferencing = 211 +Cyclomatic complexity = 80 diff --git a/ioccc/.frama-c/2020_giles_prog.parse/warnings.log b/ioccc/.frama-c/2020_giles_prog.parse/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..7649117e625db2409238127dc74c415119fbb532 --- /dev/null +++ b/ioccc/.frama-c/2020_giles_prog.parse/warnings.log @@ -0,0 +1,2 @@ +2020/giles/prog.c:33:[kernel:parser:decimal-float] warning: Floating-point constant 0.994 is not represented exactly. Will use 0x1.fced916872b02p-1. +(warn-once: no further messages from category 'parser:decimal-float' will be emitted) diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog.eva/alarms.csv b/ioccc/.frama-c/2020_kurdyukov1_prog.eva/alarms.csv new file mode 100644 index 0000000000000000000000000000000000000000..24a13b6f8eb7046288111a86bf90b3c481d532e1 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog.eva/alarms.csv @@ -0,0 +1,5 @@ +directory file line function property kind status property +2020/kurdyukov1 prog.c 19 main index_bound Unknown 0 ≤ (long)(4 + (long)(n / 4)) +2020/kurdyukov1 prog.c 20 main signed_overflow Unknown -9223372036854775808 ≤ n - 1 +2020/kurdyukov1 prog.c 20 main signed_overflow Unknown g + 8 ≤ 9223372036854775807 +2020/kurdyukov1 prog.c 21 main shift Invalid or unreachable 0 ≤ (long)(~e) diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog.eva/metrics.log b/ioccc/.frama-c/2020_kurdyukov1_prog.eva/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..9254ae7371662dca2729afb5e2049b935e4d8368 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog.eva/metrics.log @@ -0,0 +1,9 @@ +[metrics] Eva coverage statistics +======================= +Syntactically reachable functions = 1 (out of 1) +Semantically reached functions = 1 +Coverage estimation = 100.0% +[metrics] Statements analyzed by Eva +-------------------------- +107 stmts in analyzed functions, 60 stmts analyzed (56.1%) +main: 60 stmts out of 107 (56.1%) diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog.eva/nonterm.log b/ioccc/.frama-c/2020_kurdyukov1_prog.eva/nonterm.log new file mode 100644 index 0000000000000000000000000000000000000000..e94386b6f2c41a5476f87cb1092434055d1dc561 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog.eva/nonterm.log @@ -0,0 +1,4 @@ +2020/kurdyukov1/prog.c:17:[nonterm] warning: non-terminating loop +stack: main +2020/kurdyukov1/prog.c:21:[nonterm] warning: non-terminating statement +stack: main diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog.eva/warnings.log b/ioccc/.frama-c/2020_kurdyukov1_prog.eva/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog.parse/framac.ast b/ioccc/.frama-c/2020_kurdyukov1_prog.parse/framac.ast new file mode 100644 index 0000000000000000000000000000000000000000..6dab7332c2a1bf3eac301afd6f79cba1116d1996 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog.parse/framac.ast @@ -0,0 +1,122 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "stdarg.h" +#include "stddef.h" +#include "stdint.h" +#include "stdio.h" +int main(void) +{ + int __retres; + int64_t e; + int64_t k; + int64_t n; + uint32_t h[20] = {(unsigned int)0}; + uint32_t i = (unsigned int)0; + uint32_t x = ~ i / (uint32_t)15; + uint32_t f = x * x - x; + uint32_t a = f ^ x; + uint32_t b = f ^ x * (uint32_t)9; + uint32_t c = ~ a; + uint32_t d = ~ b; + int64_t z = (long)0; + int64_t g = (long)0; + int64_t l = (long)566548; + int64_t p = (long)585873; + int64_t o = (long)882346; + int64_t m = (long)64336; + while (1) { + i = (unsigned int)0; + h[i] += a; + a = h[i]; + h[1] += b; + b = h[1]; + h[2] += c; + c = h[2]; + h[3] += d; + d = h[3]; + if (! f) break; + n = (long)64; + while (1) { + int64_t tmp_2; + int64_t tmp_1; + if (n == (int64_t)8) { + h[5] = (unsigned int)g; + h[4] = (unsigned int)(g >> 32); + f = (unsigned int)(z >= (int64_t)0); + tmp_2 = (long)f; + } + else tmp_2 = n; + if (! tmp_2) break; + n -= (int64_t)1; + if (z < (int64_t)0) tmp_1 = (long)0; + else { + int64_t tmp_0; + int tmp; + tmp = getchar(); + z = (long)tmp; + if (z >= (int64_t)0) { + g += (int64_t)8; + tmp_0 = z; + } + else tmp_0 = (long)128; + tmp_1 = tmp_0; + } + x = (unsigned int)((tmp_1 << 24) | (long)(x >> 8)); + h[(int64_t)4 + n / (int64_t)4] = x; + } + e = (long)0; + k = ~ e << 40; + while (1) { + unsigned int tmp_5; + uint32_t tmp_6; + x = i / (uint32_t)16; + if (! (x < (uint32_t)4)) break; + n = (((e * m + k * p) >> 21) + e * l) + k * o; + k = ((((k * m - e * p) >> 21) + k * l) - e * o) >> 20; + e = n >> 20; + n = (long)((((((i | (unsigned int)12) * (unsigned int)152) % (unsigned int)543) % (unsigned int)82) % (unsigned int)4 + + ((i % (unsigned int)4) * (unsigned int)43) / (unsigned int)8) + (unsigned int)4); + if (x > (uint32_t)2) tmp_5 = ~ d | b; + else { + unsigned int tmp_4; + if (x > (uint32_t)1) tmp_4 = b ^ d; + else { + unsigned int tmp_3; + if (x) tmp_3 = (b ^ c) & d; else tmp_3 = (c ^ d) & ~ b; + tmp_4 = tmp_3; + } + tmp_5 = tmp_4; + } + tmp_6 = i; + i += (uint32_t)1; + x = (unsigned int)((long)((a + (tmp_5 ^ c)) + h[(unsigned int)19 - + (((x * (uint32_t)7) / (uint32_t)2 & (unsigned int)5) - + ~ (x * (uint32_t)5 & (unsigned int)6) * tmp_6) % (unsigned int)16]) + ( + (e >> 40) ^ (e >> 8))); + a = d; + d = c; + c = b; + b += (x << n) | (x >> ((int64_t)32 - n)); + } + } + while (i < (uint32_t)33) { + uint32_t tmp_9; + uint32_t tmp_7; + a = (h[i / (uint32_t)8] >> ((i % (unsigned int)8) * (unsigned int)4 ^ (unsigned int)4)) & (unsigned int)15; + tmp_7 = i; + i += (uint32_t)1; + ; + if (tmp_7 < (uint32_t)32) { + int tmp_8; + if (a > (uint32_t)9) tmp_8 = 'a' - 10; else tmp_8 = '0'; + a += (uint32_t)tmp_8; + tmp_9 = a; + } + else tmp_9 = (unsigned int)'\n'; + putchar((int)tmp_9); + } + __retres = 0; + return __retres; +} + + diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog.parse/metrics.log b/ioccc/.frama-c/2020_kurdyukov1_prog.parse/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..9ce252b059d0f3331b5285b149ff6234eab65895 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog.parse/metrics.log @@ -0,0 +1,34 @@ +[metrics] Defined functions (1) +===================== + main (0 call); + +Specified-only functions (0) +============================ + + +Undefined and unspecified functions (0) +======================================= + + +'Extern' global variables (0) +============================= + + +Potential entry points (1) +========================== + main; + +Global metrics +============== +Sloc = 107 +Decision point = 12 +Global variables = 0 +If = 12 +Loop = 4 +Goto = 0 +Assignment = 68 +Exit point = 1 +Function = 1 +Function call = 2 +Pointer dereferencing = 0 +Cyclomatic complexity = 13 diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog.parse/warnings.log b/ioccc/.frama-c/2020_kurdyukov1_prog.parse/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_extra.eva/alarms.csv b/ioccc/.frama-c/2020_kurdyukov1_prog_extra.eva/alarms.csv new file mode 100644 index 0000000000000000000000000000000000000000..cffbdf5d149718ad75dc0e842f8a705e52853597 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog_extra.eva/alarms.csv @@ -0,0 +1,5 @@ +directory file line function property kind status property +2020/kurdyukov1 prog.extra.c 25 main index_bound Unknown (long)((long)(tmp / 4) + 4) < 20 +2020/kurdyukov1 prog.extra.c 25 main signed_overflow Unknown n + 1 ≤ 9223372036854775807 +2020/kurdyukov1 prog.extra.c 26 main signed_overflow Unknown g + 8 ≤ 9223372036854775807 +2020/kurdyukov1 prog.extra.c 31 main float_to_int Unknown \mul_double(tmp_9, (double)8) * (double)((int)(8 << 26)) < 4294967296 diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_extra.eva/metrics.log b/ioccc/.frama-c/2020_kurdyukov1_prog_extra.eva/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..d5450a618776eb52982efbdf9493d193c0db1d12 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog_extra.eva/metrics.log @@ -0,0 +1,9 @@ +[metrics] Eva coverage statistics +======================= +Syntactically reachable functions = 1 (out of 1) +Semantically reached functions = 1 +Coverage estimation = 100.0% +[metrics] Statements analyzed by Eva +-------------------------- +105 stmts in analyzed functions, 105 stmts analyzed (100.0%) +main: 105 stmts out of 105 (100.0%) diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_extra.eva/nonterm.log b/ioccc/.frama-c/2020_kurdyukov1_prog_extra.eva/nonterm.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_extra.eva/warnings.log b/ioccc/.frama-c/2020_kurdyukov1_prog_extra.eva/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_extra.parse/framac.ast b/ioccc/.frama-c/2020_kurdyukov1_prog_extra.parse/framac.ast new file mode 100644 index 0000000000000000000000000000000000000000..d1bb8eff22e0c77fcc0830dea12ba3e059abf994 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog_extra.parse/framac.ast @@ -0,0 +1,118 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "math.h" +#include "stdarg.h" +#include "stddef.h" +#include "stdint.h" +#include "stdio.h" +int main(void) +{ + int __retres; + int64_t n; + uint32_t i = (unsigned int)0; + uint32_t h[20] = {(unsigned int)0}; + uint32_t x = ~ i / (uint32_t)15; + uint32_t f = x * x - x; + uint32_t a = f ^ x; + uint32_t b = f ^ x * (uint32_t)9; + uint32_t c = ~ a; + uint32_t d = ~ b; + int64_t z = (long)0; + int64_t g = (long)0; + while (1) { + i = (unsigned int)0; + n = (long)i; + h[n] += a; + a = h[n]; + h[1] += b; + b = h[1]; + h[2] += c; + c = h[2]; + h[3] += d; + d = h[3]; + if (! f) break; + while (1) { + uint32_t tmp_3; + int64_t tmp; + int64_t tmp_2; + if (n == (int64_t)56) { + h[18] = (unsigned int)g; + h[19] = (unsigned int)(g >> 32); + f = (unsigned int)(z >= (int64_t)0); + tmp_3 = f; + } + else tmp_3 = (unsigned int)(n < (int64_t)64); + if (! tmp_3) break; + tmp = n; + n += (int64_t)1; + if (z < (int64_t)0) tmp_2 = (long)0; + else { + int64_t tmp_1; + int tmp_0; + tmp_0 = getchar(); + z = (long)tmp_0; + if (z >= (int64_t)0) { + g += (int64_t)8; + tmp_1 = z; + } + else tmp_1 = (long)128; + tmp_2 = tmp_1; + } + x = (unsigned int)((tmp_2 << 24) | (long)(x >> 8)); + h[tmp / (int64_t)4 + (int64_t)4] = x; + } + while (1) { + unsigned int tmp_6; + uint32_t tmp_7; + double tmp_9; + double tmp_8; + x = i >> 4; + if (! (x < (uint32_t)4)) break; + n = (long)((((((i | (unsigned int)12) * (unsigned int)152) % (unsigned int)543) % (unsigned int)82) % (unsigned int)4 + + ((i % (unsigned int)4) * (unsigned int)43) / (unsigned int)8) + (unsigned int)4); + if (x > (uint32_t)2) tmp_6 = ~ d | b; + else { + unsigned int tmp_5; + if (x > (uint32_t)1) tmp_5 = b ^ d; + else { + unsigned int tmp_4; + if (x) tmp_4 = (b ^ c) & d; else tmp_4 = (c ^ d) & ~ b; + tmp_5 = tmp_4; + } + tmp_6 = tmp_5; + } + tmp_7 = i; + i += (uint32_t)1; + x = (a + (tmp_6 ^ c)) + h[(((x * (uint32_t)7) / (uint32_t)2 & (unsigned int)5) - + ~ (x * (uint32_t)5 & (unsigned int)6) * tmp_7) % (unsigned int)16 + (unsigned int)4]; + tmp_8 = sin((double)i); + tmp_9 = fabs(tmp_8); + a = (unsigned int)((tmp_9 * (double)8) * (double)(8 << 26)); + x += a; + a = d; + d = c; + c = b; + b += (x << n) | (x >> ((int64_t)32 - n)); + } + } + while (n < (int64_t)33) { + uint32_t tmp_12; + int64_t tmp_10; + a = (h[n / (int64_t)8] >> ((n % (long)8) * (long)4 ^ (long)4)) & (unsigned int)15; + tmp_10 = n; + n += (int64_t)1; + ; + if (tmp_10 < (int64_t)32) { + int tmp_11; + if (a > (uint32_t)9) tmp_11 = 'a' - 10; else tmp_11 = '0'; + a += (uint32_t)tmp_11; + tmp_12 = a; + } + else tmp_12 = (unsigned int)'\n'; + putchar((int)tmp_12); + } + __retres = 0; + return __retres; +} + + diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_extra.parse/metrics.log b/ioccc/.frama-c/2020_kurdyukov1_prog_extra.parse/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..bc53c0a77c093b334cd79696966a44a134f4f7fd --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog_extra.parse/metrics.log @@ -0,0 +1,34 @@ +[metrics] Defined functions (1) +===================== + main (0 call); + +Specified-only functions (0) +============================ + + +Undefined and unspecified functions (0) +======================================= + + +'Extern' global variables (0) +============================= + + +Potential entry points (1) +========================== + main; + +Global metrics +============== +Sloc = 105 +Decision point = 12 +Global variables = 0 +If = 12 +Loop = 4 +Goto = 0 +Assignment = 64 +Exit point = 1 +Function = 1 +Function call = 4 +Pointer dereferencing = 0 +Cyclomatic complexity = 13 diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_extra.parse/warnings.log b/ioccc/.frama-c/2020_kurdyukov1_prog_extra.parse/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_orig.eva/alarms.csv b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.eva/alarms.csv new file mode 100644 index 0000000000000000000000000000000000000000..784cbba878a8b54bcbfcbb885ff25a368e24d70e --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.eva/alarms.csv @@ -0,0 +1,4 @@ +directory file line function property kind status property +2020/kurdyukov1 prog.orig.c 11 main index_bound Unknown (unsigned int)(tmp_2 / 4) < 16 +2020/kurdyukov1 prog.orig.c 11 main signed_overflow Unknown g + 8 ≤ 9223372036854775807 +2020/kurdyukov1 prog.orig.c 13 main shift Invalid or unreachable 0 ≤ (long)(~e) diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_orig.eva/metrics.log b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.eva/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..03dec3298dd99b2b5825bc754c33e6a74ceb239f --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.eva/metrics.log @@ -0,0 +1,9 @@ +[metrics] Eva coverage statistics +======================= +Syntactically reachable functions = 1 (out of 1) +Semantically reached functions = 1 +Coverage estimation = 100.0% +[metrics] Statements analyzed by Eva +-------------------------- +106 stmts in analyzed functions, 69 stmts analyzed (65.1%) +main: 69 stmts out of 106 (65.1%) diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_orig.eva/nonterm.log b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.eva/nonterm.log new file mode 100644 index 0000000000000000000000000000000000000000..a166e50d5770da115dc85b6164439862acee8250 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.eva/nonterm.log @@ -0,0 +1,2 @@ +2020/kurdyukov1/prog.orig.c:13:[nonterm] warning: non-terminating statement +stack: main diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_orig.eva/warnings.log b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.eva/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_orig.parse/framac.ast b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.parse/framac.ast new file mode 100644 index 0000000000000000000000000000000000000000..b8ab87576724c0e2fa7393764940e5d6e447999b --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.parse/framac.ast @@ -0,0 +1,128 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "stdarg.h" +#include "stddef.h" +#include "stdint.h" +#include "stdio.h" +int main(void) +{ + int __retres; + uint32_t i; + uint32_t x; + uint32_t s[16]; + int64_t e; + int64_t k; + int64_t y; + uint32_t f = (unsigned int)0; + uint32_t n = (unsigned int)0; + uint32_t a = (unsigned int)1732584193; + uint32_t b = 4023233417; + uint32_t q = (unsigned int)32; + uint32_t c = ~ a; + uint32_t d = ~ b; + x = a; + uint32_t h[8] = + {x, + b, + c, + d, + (unsigned int)80200, + (unsigned int)745, + (unsigned int)108189, + (unsigned int)38200}; + int64_t z = (long)0; + int64_t g = (long)0; + int64_t l = (long)566548; + int64_t m = (long)64336; + int64_t o = (long)882346; + int64_t p = (long)585873; + while (! f) { + uint32_t tmp_2; + int64_t tmp_5; + uint32_t tmp_6; + tmp_2 = n; + n += (uint32_t)1; + if (z < (int64_t)0) tmp_5 = (long)0; + else { + int64_t tmp_4; + int tmp_3; + tmp_3 = getchar(); + z = (long)tmp_3; + if (z >= (int64_t)0) { + g += (int64_t)8; + tmp_4 = z; + } + else tmp_4 = (long)128; + tmp_5 = tmp_4; + } + x = (unsigned int)((long)(x >> 8) | (tmp_5 << 24)); + s[tmp_2 / (uint32_t)4] = x; + if (n == (uint32_t)56) { + s[14] = (unsigned int)g; + s[15] = (unsigned int)(g >> q); + f = (unsigned int)(z < (int64_t)0); + tmp_6 = f; + } + else tmp_6 = n / (uint32_t)64; + if (tmp_6) { + i = (unsigned int)0; + e = (long)i; + k = ~ e << 40; + while (i < (uint32_t)64) { + unsigned int tmp_1; + y = (((e * m + k * p) >> 21) + e * l) + k * o; + k = ((((k * m - e * p) >> 21) + k * l) - e * o) >> 20; + e = y >> 20; + x = i / (uint32_t)16 + (uint32_t)4; + n = h[x]; + if (x > (uint32_t)4) { + unsigned int tmp_0; + if (x > (uint32_t)6) tmp_0 = ~ d | b; + else { + unsigned int tmp; + if (x > (uint32_t)5) tmp = b ^ d; else tmp = (b ^ c) & d; + tmp_0 = tmp; + } + tmp_1 = tmp_0 ^ c; + } + else tmp_1 = ((c ^ d) & b) ^ d; + x = (unsigned int)((long)((a + tmp_1) + s[(((n / (uint32_t)8) % (unsigned int)8) * i + + n % (unsigned int)8) & (unsigned int)15]) + ( + (e >> 8) ^ (e >> 40))); + n = (((n >> ((i % (unsigned int)4) * (unsigned int)3 + (unsigned int)6)) & (unsigned int)7) + + (i % (unsigned int)4) * (unsigned int)6) + (unsigned int)2; + i += (uint32_t)1; + a = d; + d = c; + c = b; + b += (x << n) | (x >> (q - n)); + } + n = (unsigned int)0; + h[n] += a; + a = h[n]; + h[1] += b; + b = h[1]; + h[2] += c; + c = h[2]; + h[3] += d; + d = h[3]; + } + } + while (n < (uint32_t)33) { + uint32_t tmp_8; + a = (h[n / (uint32_t)8] >> ((n % (unsigned int)8) * (unsigned int)4 ^ (unsigned int)4)) & (unsigned int)15; + n += (uint32_t)1; + ; + if (n > q) tmp_8 = (unsigned int)'\n'; + else { + int tmp_7; + if (a < (uint32_t)10) tmp_7 = '0'; else tmp_7 = 'a' - 10; + tmp_8 = a + (uint32_t)tmp_7; + } + putchar((int)tmp_8); + } + __retres = 0; + return __retres; +} + + diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_orig.parse/metrics.log b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.parse/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..6302ba07b27101bd546b075b947531515ea029df --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.parse/metrics.log @@ -0,0 +1,34 @@ +[metrics] Defined functions (1) +===================== + main (0 call); + +Specified-only functions (0) +============================ + + +Undefined and unspecified functions (0) +======================================= + + +'Extern' global variables (0) +============================= + + +Potential entry points (1) +========================== + main; + +Global metrics +============== +Sloc = 106 +Decision point = 12 +Global variables = 0 +If = 12 +Loop = 3 +Goto = 0 +Assignment = 68 +Exit point = 1 +Function = 1 +Function call = 2 +Pointer dereferencing = 0 +Cyclomatic complexity = 13 diff --git a/ioccc/.frama-c/2020_kurdyukov1_prog_orig.parse/warnings.log b/ioccc/.frama-c/2020_kurdyukov1_prog_orig.parse/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.eva/alarms.csv b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.eva/alarms.csv new file mode 100644 index 0000000000000000000000000000000000000000..fe2c349dcbf5a75556a19408f30b17c767d2f936 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.eva/alarms.csv @@ -0,0 +1,7 @@ +directory file line function property kind status property +2020/kurdyukov2 prog.ppm.c 17 main mem_access Unknown \valid_read(V) +2020/kurdyukov2 prog.ppm.c 17 main precondition of atoi Unknown valid_nptr: \valid_read(nptr) +2020/kurdyukov2 prog.ppm.c 18 main mem_access Invalid or unreachable \valid_read(V) +FRAMAC_SHARE/libc stdio.h 150 fopen precondition Unknown valid_filename: valid_read_string(filename) +FRAMAC_SHARE/libc stdio.h 151 fopen precondition Unknown valid_mode: valid_read_string(mode) +FRAMAC_SHARE/libc stdlib.h 78 atoi precondition Unknown valid_nptr: \valid_read(nptr) diff --git a/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.eva/metrics.log b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.eva/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..f5bc321203a69290faa38fb33515da7257034eed --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.eva/metrics.log @@ -0,0 +1,9 @@ +[metrics] Eva coverage statistics +======================= +Syntactically reachable functions = 1 (out of 1) +Semantically reached functions = 1 +Coverage estimation = 100.0% +[metrics] Statements analyzed by Eva +-------------------------- +746 stmts in analyzed functions, 19 stmts analyzed (2.5%) +main: 19 stmts out of 746 (2.5%) diff --git a/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.eva/nonterm.log b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.eva/nonterm.log new file mode 100644 index 0000000000000000000000000000000000000000..f9f67632d794babc71f1799e847e51caf516a0a6 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.eva/nonterm.log @@ -0,0 +1,2 @@ +2020/kurdyukov2/prog.ppm.c:18:[nonterm] warning: non-terminating function call +stack: main diff --git a/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.eva/warnings.log b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.eva/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.parse/framac.ast b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.parse/framac.ast new file mode 100644 index 0000000000000000000000000000000000000000..50b07da3b155f02402b0078bdbc40ab867e80664 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.parse/framac.ast @@ -0,0 +1,792 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "stdarg.h" +#include "stddef.h" +#include "stdint.h" +#include "stdio.h" +#include "stdlib.h" +struct __anonstruct_P_1 { + uint16_t x ; + uint16_t y ; + uint16_t w ; + uint16_t h ; + uint8_t c[4] ; + int64_t d ; +}; +/*@ requires valid_read_string(format); + assigns \result, stream->__fc_FILE_data; + assigns \result + \from (indirect: stream->__fc_FILE_id), + (indirect: stream->__fc_FILE_data), + (indirect: *(format + (0 ..))), (indirect: param1), + (indirect: param0); + assigns stream->__fc_FILE_data + \from (indirect: stream->__fc_FILE_id), stream->__fc_FILE_data, + (indirect: *(format + (0 ..))), param1, param0; + */ +int fprintf_va_1(FILE * __restrict stream, char const * __restrict format, + int param0, int param1); + +int main(int c, char **V) +{ + int __retres; + while (c == 4) { + struct __anonstruct_P_1 *P; + struct __anonstruct_P_1 *N; + struct __anonstruct_P_1 *X; + struct __anonstruct_P_1 o; + void *O; + void *F; + int64_t *p; + int64_t e; + int64_t f; + int64_t u; + int64_t K; + int64_t L; + int64_t *t; + int64_t Q; + uint8_t *d; + int tmp; + intptr_t w; + intptr_t h; + intptr_t s; + intptr_t S; + intptr_t j; + intptr_t y; + intptr_t v; + intptr_t q; + intptr_t l; + intptr_t k; + intptr_t z; + int tmp_8; + uint16_t tmp_44; + int64_t U = (long)1; + V ++; + ; + tmp = atoi((char const *)*V); + intptr_t n = (long)tmp; + intptr_t b = (long)3; + intptr_t i = (long)0; + intptr_t x = (long)0; + V ++; + ; + F = (void *)fopen((char const *)*V,"rb"); + if (! F) break; + tmp_8 = fgetc((FILE *)F); + if (tmp_8 == 'P') { + int tmp_7; + k = (long)0; + i = (long)(-0); + while (! k) { + while (1) { + int tmp_3; + int tmp_6; + intptr_t tmp_4; + tmp_3 = fgetc((FILE *)F); + z = (long)tmp_3; + tmp_4 = k; + k += (intptr_t)1; + ; + if (tmp_4) { + int tmp_5; + if (z - (intptr_t)'\n') + if (z - (intptr_t)(-1)) tmp_5 = 1; else tmp_5 = 0; + else tmp_5 = 0; + tmp_6 = tmp_5; + } + else tmp_6 = z == (intptr_t)'#'; + if (! tmp_6) break; + } + if (z - (intptr_t)' ') { + if (z - (intptr_t)'\n') { + if (z - (intptr_t)'\r') { + if (z - (intptr_t)'\t') { + if (z - (intptr_t)(-1)) { + intptr_t tmp_1; + if (z < (intptr_t)'0') { + i = (long)(-1); + tmp_1 = i; + } + else + if (z > (intptr_t)'9') { + i = (long)(-1); + tmp_1 = i; + } + else { + intptr_t tmp_0; + if (i < (intptr_t)0) tmp_0 = (long)0; + else tmp_0 = i * (intptr_t)10; + i = (tmp_0 + z) - (intptr_t)'0'; + if (i >> 15) { + i = (long)(-1); + tmp_1 = i; + } + else tmp_1 = (long)0; + } + k = tmp_1; + } + else goto _LAND_2; + } + else goto _LAND_2; + } + else goto _LAND_2; + } + else goto _LAND_2; + } + else { + int tmp_2; + _LAND_2: + if (i >= (intptr_t)0) tmp_2 = 1; + else + if (z >> 8) tmp_2 = 1; else tmp_2 = 0; + k = (long)tmp_2; + } + } + if (i - (intptr_t)3) + if (i - (intptr_t)6) tmp_7 = 1; else tmp_7 = 0; + else tmp_7 = 0; + if (tmp_7) break; + } + k = (long)0; + w = (long)(-1); + while (! k) { + while (1) { + int tmp_12; + int tmp_15; + intptr_t tmp_13; + tmp_12 = fgetc((FILE *)F); + z = (long)tmp_12; + tmp_13 = k; + k += (intptr_t)1; + ; + if (tmp_13) { + int tmp_14; + if (z - (intptr_t)'\n') + if (z - (intptr_t)(-1)) tmp_14 = 1; else tmp_14 = 0; + else tmp_14 = 0; + tmp_15 = tmp_14; + } + else tmp_15 = z == (intptr_t)'#'; + if (! tmp_15) break; + } + if (z - (intptr_t)' ') { + if (z - (intptr_t)'\n') { + if (z - (intptr_t)'\r') { + if (z - (intptr_t)'\t') { + if (z - (intptr_t)(-1)) { + intptr_t tmp_10; + if (z < (intptr_t)'0') { + w = (long)(-1); + tmp_10 = w; + } + else + if (z > (intptr_t)'9') { + w = (long)(-1); + tmp_10 = w; + } + else { + intptr_t tmp_9; + if (w < (intptr_t)0) tmp_9 = (long)0; + else tmp_9 = w * (intptr_t)10; + w = (tmp_9 + z) - (intptr_t)'0'; + if (w >> 15) { + w = (long)(-1); + tmp_10 = w; + } + else tmp_10 = (long)0; + } + k = tmp_10; + } + else goto _LAND_6; + } + else goto _LAND_6; + } + else goto _LAND_6; + } + else goto _LAND_6; + } + else { + int tmp_11; + _LAND_6: + if (w >= (intptr_t)0) tmp_11 = 1; + else + if (z >> 8) tmp_11 = 1; else tmp_11 = 0; + k = (long)tmp_11; + } + } + if (w < (intptr_t)1) break; + k = (long)0; + h = (long)(-1); + while (! k) { + while (1) { + int tmp_20; + int tmp_23; + intptr_t tmp_21; + tmp_20 = fgetc((FILE *)F); + z = (long)tmp_20; + tmp_21 = k; + k += (intptr_t)1; + ; + if (tmp_21) { + int tmp_22; + if (z - (intptr_t)'\n') + if (z - (intptr_t)(-1)) tmp_22 = 1; else tmp_22 = 0; + else tmp_22 = 0; + tmp_23 = tmp_22; + } + else tmp_23 = z == (intptr_t)'#'; + if (! tmp_23) break; + } + if (z - (intptr_t)' ') { + if (z - (intptr_t)'\n') { + if (z - (intptr_t)'\r') { + if (z - (intptr_t)'\t') { + if (z - (intptr_t)(-1)) { + intptr_t tmp_18; + if (z < (intptr_t)'0') { + h = (long)(-1); + tmp_18 = h; + } + else + if (z > (intptr_t)'9') { + h = (long)(-1); + tmp_18 = h; + } + else { + intptr_t tmp_17; + if (h < (intptr_t)0) tmp_17 = (long)0; + else tmp_17 = h * (intptr_t)10; + h = (tmp_17 + z) - (intptr_t)'0'; + if (h >> 15) { + h = (long)(-1); + tmp_18 = h; + } + else tmp_18 = (long)0; + } + k = tmp_18; + } + else goto _LAND_10; + } + else goto _LAND_10; + } + else goto _LAND_10; + } + else goto _LAND_10; + } + else { + int tmp_19; + _LAND_10: + if (h >= (intptr_t)0) tmp_19 = 1; + else + if (z >> 8) tmp_19 = 1; else tmp_19 = 0; + k = (long)tmp_19; + } + } + if (h < (intptr_t)1) break; + k = (long)0; + y = (long)(-1); + while (! k) { + while (1) { + int tmp_28; + int tmp_31; + intptr_t tmp_29; + tmp_28 = fgetc((FILE *)F); + z = (long)tmp_28; + tmp_29 = k; + k += (intptr_t)1; + ; + if (tmp_29) { + int tmp_30; + if (z - (intptr_t)'\n') + if (z - (intptr_t)(-1)) tmp_30 = 1; else tmp_30 = 0; + else tmp_30 = 0; + tmp_31 = tmp_30; + } + else tmp_31 = z == (intptr_t)'#'; + if (! tmp_31) break; + } + if (z - (intptr_t)' ') { + if (z - (intptr_t)'\n') { + if (z - (intptr_t)'\r') { + if (z - (intptr_t)'\t') { + if (z - (intptr_t)(-1)) { + intptr_t tmp_26; + if (z < (intptr_t)'0') { + y = (long)(-1); + tmp_26 = y; + } + else + if (z > (intptr_t)'9') { + y = (long)(-1); + tmp_26 = y; + } + else { + intptr_t tmp_25; + if (y < (intptr_t)0) tmp_25 = (long)0; + else tmp_25 = y * (intptr_t)10; + y = (tmp_25 + z) - (intptr_t)'0'; + if (y >> 15) { + y = (long)(-1); + tmp_26 = y; + } + else tmp_26 = (long)0; + } + k = tmp_26; + } + else goto _LAND_14; + } + else goto _LAND_14; + } + else goto _LAND_14; + } + else goto _LAND_14; + } + else { + int tmp_27; + _LAND_14: + if (y >= (intptr_t)0) tmp_27 = 1; + else + if (z >> 8) tmp_27 = 1; else tmp_27 = 0; + k = (long)tmp_27; + } + } + if (y - (intptr_t)255) break; + if (n < (intptr_t)1) n = (long)1; + else { + intptr_t tmp_33; + if (n > w * h) tmp_33 = w * h; else tmp_33 = n; + n = tmp_33; + } + L = n; + s = w * b; + S = s + b; + K = S; + u = K * h + K; + K = (long)(sizeof(*X) * (unsigned long)L + (unsigned long)(u * (int64_t)9)); + L = (long)((unsigned long)K); + ; + if (K - L) break; + else { + t = (int64_t *)malloc((unsigned long)K); + if (! t) break; + } + O = (void *)(t + u); + P = (struct __anonstruct_P_1 *)O; + X = P; + O = (void *)(P + n); + d = (uint8_t *)O; + if (i < (intptr_t)4) + while (x < s * h) { + intptr_t tmp_41; + k = (long)0; + i = (long)(-1); + while (! k) { + while (1) { + int tmp_37; + int tmp_40; + intptr_t tmp_38; + tmp_37 = fgetc((FILE *)F); + z = (long)tmp_37; + tmp_38 = k; + k += (intptr_t)1; + ; + if (tmp_38) { + int tmp_39; + if (z - (intptr_t)'\n') + if (z - (intptr_t)(-1)) tmp_39 = 1; else tmp_39 = 0; + else tmp_39 = 0; + tmp_40 = tmp_39; + } + else tmp_40 = z == (intptr_t)'#'; + if (! tmp_40) break; + } + if (z - (intptr_t)' ') { + if (z - (intptr_t)'\n') { + if (z - (intptr_t)'\r') { + if (z - (intptr_t)'\t') { + if (z - (intptr_t)(-1)) { + intptr_t tmp_35; + if (z < (intptr_t)'0') { + i = (long)(-1); + tmp_35 = i; + } + else + if (z > (intptr_t)'9') { + i = (long)(-1); + tmp_35 = i; + } + else { + intptr_t tmp_34; + if (i < (intptr_t)0) tmp_34 = (long)0; + else tmp_34 = i * (intptr_t)10; + i = (tmp_34 + z) - (intptr_t)'0'; + if (i >> 15) { + i = (long)(-1); + tmp_35 = i; + } + else tmp_35 = (long)0; + } + k = tmp_35; + } + else goto _LAND_18; + } + else goto _LAND_18; + } + else goto _LAND_18; + } + else goto _LAND_18; + } + else { + int tmp_36; + _LAND_18: + if (i >= (intptr_t)0) tmp_36 = 1; + else + if (z >> 8) tmp_36 = 1; else tmp_36 = 0; + k = (long)tmp_36; + } + } + tmp_41 = x; + x += (intptr_t)1; + *(d + tmp_41) = (unsigned char)i; + i >>= 8; + if (i) break; + } + else { + size_t tmp_43; + tmp_43 = fread((void *)d,(unsigned long)s,(unsigned long)h,(FILE *)F); + i = (long)((size_t)h - tmp_43); + } + fclose((FILE *)F); + if (i) break; + j = (long)0; + tmp_44 = (unsigned short)j; + X->y = tmp_44; + X->x = tmp_44; + while (j < b) { + x = j - S; + z = j - b; + while (x < S * h) { + if (x < (intptr_t)0) { + y = (long)0; + *(t + (x + S)) = y; + } + else { + intptr_t tmp_45; + tmp_45 = y; + y -= (intptr_t)1; + ; + if (tmp_45) { + z += b; + u += (int64_t)*(d + z); + } + else { + y = w; + u = (long)0; + } + *(t + (x + S)) = *(t + x) + u; + } + x += b; + } + j += (intptr_t)1; + } + X->w = (unsigned short)w; + X->h = (unsigned short)h; + { + int x_0; + int Z = (int)X->x; + int y_0 = (int)X->y; + int w_0 = (int)X->w; + int h_0 = (int)X->h; + p = (t + (intptr_t)Z * b) + (intptr_t)y_0 * S; + l = (long)(w_0 * h_0); + j = (long)0; + u = j; + while (1) { + intptr_t tmp_46; + if (l) { + if (! (j < b)) break; + } + else break; + tmp_46 = j; + j += (intptr_t)1; + X->c[tmp_46] = (unsigned char)(((((*(p + ((intptr_t)w_0 * b + + (intptr_t)h_0 * S)) - *( + p + (intptr_t)w_0 * b)) - *( + p + (intptr_t)h_0 * S)) + *p) + + l / (intptr_t)2) / l); + p ++; + } + while (1) { + int tmp_47; + tmp_47 = h_0; + h_0 --; + ; + if (! tmp_47) break; + x_0 = Z; + while (x_0 < w_0 + Z) { + j = (long)0; + while (j < b) { + z = (long)((int)*(d + (((intptr_t)y_0 * s + (intptr_t)x_0 * b) + j)) - (int)X->c[j]); + u += z * z; + j += (intptr_t)1; + } + x_0 ++; + } + y_0 ++; + } + X->d = u; + } + while (1) { + int tmp_59; + X = P; + N = X; + if (U) { + i += (intptr_t)1; + ; + if (i < n) tmp_59 = 1; else tmp_59 = 0; + } + else tmp_59 = 0; + if (! tmp_59) break; + j = (long)0; + U = j; + while (1) { + intptr_t tmp_48; + tmp_48 = j; + j += (intptr_t)1; + ; + if (! (tmp_48 < i)) break; + if (X->d > U) { + N = X; + U = N->d; + } + else U = U; + X ++; + } + o = *N; + v = (long)o.w; + q = (long)o.h; + x = (long)o.x; + y = (long)o.y; + k = (long)0; + z = k; + e = z; + while (1) { + z += (intptr_t)1; + ; + if (! (z < v)) break; + j = (long)0; + u = j; + while (1) { + int64_t tmp_49; + int64_t tmp_50; + p = ((t + x * b) + y * S) + j; + if (! (j < b)) break; + K = *(p + (z * b + q * S)) - *(p + z * b); + Q = (intptr_t)N->c[j] * q; + L = ((*(p + (v * b + q * S)) - *(p + v * b)) - K) - Q * (v - z); + K -= (*(p + q * S) - *p) + Q * z; + if (L < (int64_t)0) tmp_49 = - L; else tmp_49 = L; + u += tmp_49; + if (K < (int64_t)0) tmp_50 = - K; else tmp_50 = K; + u += tmp_50; + j += (intptr_t)1; + } + if (u > e) { + e = u; + k = z; + intptr_t tmp_16 = k; + } + } + l = (long)0; + z = l; + f = z; + while (1) { + z += (intptr_t)1; + ; + if (! (z < q)) break; + j = (long)0; + u = j; + while (1) { + int64_t tmp_51; + int64_t tmp_52; + p = ((t + x * b) + y * S) + j; + if (! (j < b)) break; + K = *(p + (z * S + v * b)) - *(p + z * S); + Q = (intptr_t)N->c[j] * v; + L = ((*(p + (q * S + v * b)) - *(p + q * S)) - K) - Q * (q - z); + K -= (*(p + v * b) - *p) + Q * z; + if (L < (int64_t)0) tmp_51 = - L; else tmp_51 = L; + u += tmp_51; + if (K < (int64_t)0) tmp_52 = - K; else tmp_52 = K; + u += tmp_52; + j += (intptr_t)1; + } + if (u > f) { + f = u; + l = z; + intptr_t tmp_24 = l; + } + } + if (e < f) { + uint16_t tmp_53; + tmp_53 = (unsigned short)l; + N->h = tmp_53; + o.y = (unsigned short)((int)o.y + (int)tmp_53); + o.h = (unsigned short)((intptr_t)o.h - l); + uint16_t tmp_32 = o.h; + } + else { + uint16_t tmp_54; + tmp_54 = (unsigned short)k; + N->w = tmp_54; + o.x = (unsigned short)((int)o.x + (int)tmp_54); + o.w = (unsigned short)((intptr_t)o.w - k); + uint16_t tmp_42 = o.w; + } + *X = o; + { + int x_1; + int Z_0 = (int)X->x; + int y_1 = (int)X->y; + int w_1 = (int)X->w; + int h_1 = (int)X->h; + p = (t + (intptr_t)Z_0 * b) + (intptr_t)y_1 * S; + l = (long)(w_1 * h_1); + j = (long)0; + u = j; + while (1) { + intptr_t tmp_55; + if (l) { + if (! (j < b)) break; + } + else break; + tmp_55 = j; + j += (intptr_t)1; + X->c[tmp_55] = (unsigned char)(((((*(p + ((intptr_t)w_1 * b + + (intptr_t)h_1 * S)) - *( + p + (intptr_t)w_1 * b)) - *( + p + (intptr_t)h_1 * S)) + *p) + + l / (intptr_t)2) / l); + p ++; + } + while (1) { + int tmp_56; + tmp_56 = h_1; + h_1 --; + ; + if (! tmp_56) break; + x_1 = Z_0; + while (x_1 < w_1 + Z_0) { + j = (long)0; + while (j < b) { + z = (long)((int)*(d + (((intptr_t)y_1 * s + (intptr_t)x_1 * b) + j)) - (int)X->c[j]); + u += z * z; + j += (intptr_t)1; + } + x_1 ++; + } + y_1 ++; + } + X->d = u; + } + X = N; + { + int x_2; + int Z_1 = (int)X->x; + int y_2 = (int)X->y; + int w_2 = (int)X->w; + int h_2 = (int)X->h; + p = (t + (intptr_t)Z_1 * b) + (intptr_t)y_2 * S; + l = (long)(w_2 * h_2); + j = (long)0; + u = j; + while (1) { + intptr_t tmp_57; + if (l) { + if (! (j < b)) break; + } + else break; + tmp_57 = j; + j += (intptr_t)1; + X->c[tmp_57] = (unsigned char)(((((*(p + ((intptr_t)w_2 * b + + (intptr_t)h_2 * S)) - *( + p + (intptr_t)w_2 * b)) - *( + p + (intptr_t)h_2 * S)) + *p) + + l / (intptr_t)2) / l); + p ++; + } + while (1) { + int tmp_58; + tmp_58 = h_2; + h_2 --; + ; + if (! tmp_58) break; + x_2 = Z_1; + while (x_2 < w_2 + Z_1) { + j = (long)0; + while (j < b) { + z = (long)((int)*(d + (((intptr_t)y_2 * s + (intptr_t)x_2 * b) + j)) - (int)X->c[j]); + u += z * z; + j += (intptr_t)1; + } + x_2 ++; + } + y_2 ++; + } + X->d = u; + } + } + while (1) { + intptr_t tmp_62; + tmp_62 = i; + i -= (intptr_t)1; + ; + if (! tmp_62) break; + { + int x_3; + int Z_2 = (int)X->x; + int y_3 = (int)X->y; + int w_3 = (int)X->w; + int h_3 = (int)X->h; + while (1) { + int tmp_61; + tmp_61 = h_3; + h_3 --; + ; + if (! tmp_61) break; + x_3 = Z_2; + while (x_3 < w_3 + Z_2) { + j = (long)0; + while (j < b) { + uint8_t tmp_60; + tmp_60 = X->c[j]; + *(d + (((intptr_t)y_3 * s + (intptr_t)x_3 * b) + j)) = tmp_60; + z = (long)tmp_60; + j += (intptr_t)1; + } + x_3 ++; + } + y_3 ++; + } + } + X ++; + } + V ++; + ; + F = (void *)fopen((char const *)*V,"wb"); + if (! F) break; + ; + c = (int)w; + ; + fprintf((FILE *)F,"P6\n%i %i\n255\n",c,(int)h); /* fprintf_va_1 */ + fwrite((void const *)d,(unsigned long)s,(unsigned long)h,(FILE *)F); + fclose((FILE *)F); + free((void *)t); + __retres = 0; + goto return_label; + } + __retres = 1; + return_label: return __retres; +} + + diff --git a/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.parse/metrics.log b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.parse/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..4e2516d66b690d3fabfbadd91d76145158d789d2 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.parse/metrics.log @@ -0,0 +1,34 @@ +[metrics] Defined functions (1) +===================== + main (0 call); + +Specified-only functions (0) +============================ + + +Undefined and unspecified functions (0) +======================================= + + +'Extern' global variables (0) +============================= + + +Potential entry points (1) +========================== + main; + +Global metrics +============== +Sloc = 746 +Decision point = 137 +Global variables = 0 +If = 137 +Loop = 36 +Goto = 21 +Assignment = 346 +Exit point = 1 +Function = 1 +Function call = 16 +Pointer dereferencing = 75 +Cyclomatic complexity = 138 diff --git a/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.parse/warnings.log b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.parse/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..a3b3ea8f0446f909ad417af7fa745cc3a4ff629e --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov2_prog_ppm.parse/warnings.log @@ -0,0 +1,11 @@ +2020/kurdyukov2/prog.ppm.c:18:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov2/prog.ppm.c:18:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov2/prog.ppm.c:18:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov2/prog.ppm.c:18:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov2/prog.ppm.c:18:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov2/prog.ppm.c:18:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov2/prog.ppm.c:18:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov2/prog.ppm.c:18:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov2/prog.ppm.c:26:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov2/prog.ppm.c:26:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov2/prog.ppm.c:26:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog.eva/alarms.csv b/ioccc/.frama-c/2020_kurdyukov3_prog.eva/alarms.csv new file mode 100644 index 0000000000000000000000000000000000000000..a931e3bcb38f801c34f48e10cc519935d4be3cbc --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog.eva/alarms.csv @@ -0,0 +1,5 @@ +directory file line function property kind status property +2020/kurdyukov3 prog.c 7 main initialization Unknown \initialized(&a) +2020/kurdyukov3 prog.c 8 main initialization Unknown \initialized(&a) +2020/kurdyukov3 prog.c 8 main initialization Unknown \initialized(&t[j]) +2020/kurdyukov3 prog.c 9 main initialization Unknown \initialized(&t[i]) diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog.eva/metrics.log b/ioccc/.frama-c/2020_kurdyukov3_prog.eva/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..6d0ec759c7bf1e300970491736da64a0aa885441 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog.eva/metrics.log @@ -0,0 +1,9 @@ +[metrics] Eva coverage statistics +======================= +Syntactically reachable functions = 1 (out of 1) +Semantically reached functions = 1 +Coverage estimation = 100.0% +[metrics] Statements analyzed by Eva +-------------------------- +59 stmts in analyzed functions, 59 stmts analyzed (100.0%) +main: 59 stmts out of 59 (100.0%) diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog.eva/nonterm.log b/ioccc/.frama-c/2020_kurdyukov3_prog.eva/nonterm.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog.eva/warnings.log b/ioccc/.frama-c/2020_kurdyukov3_prog.eva/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog.parse/framac.ast b/ioccc/.frama-c/2020_kurdyukov3_prog.parse/framac.ast new file mode 100644 index 0000000000000000000000000000000000000000..69bbfa43e19a244477a20cd77aaff1c9105f1aca --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog.parse/framac.ast @@ -0,0 +1,79 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "signal.h" +#include "stdarg.h" +#include "stdio.h" +#include "stdlib.h" +#include "time.h" +int main(void) +{ + int __retres; + unsigned int a; + unsigned int t[64]; + time_t tmp; + unsigned int i = (unsigned int)1; + unsigned int j = (unsigned int)0; + tmp = time((time_t *)0); + srand((unsigned int)tmp); + while (i) + if (j) { + unsigned int tmp_5; + i --; + if (i < (unsigned int)1) { + if (a >> 8) tmp_5 = (unsigned int)0; else goto _LAND; + } + else { + unsigned int tmp_4; + unsigned int tmp_0; + unsigned int tmp_1; + _LAND: + { + if (i) tmp_0 = t[j]; else tmp_0 = a; + putchar((int)tmp_0); + tmp_1 = i; + i ++; + if (tmp_1) { + unsigned int tmp_3; + i --; + t[j] = t[i]; + if (i > (unsigned int)2) { + int tmp_2; + tmp_2 = rand(); + tmp_3 = (unsigned int)tmp_2 % (i - (unsigned int)2) + (unsigned int)2; + } + else tmp_3 = (unsigned int)1; + tmp_4 = tmp_3; + } + else tmp_4 = (unsigned int)0; + } + tmp_5 = tmp_4; + } + j = tmp_5; + } + else { + int tmp_8; + int tmp_6; + tmp_6 = getchar(); + a = (unsigned int)tmp_6; + if ((unsigned int)26 > (a | (unsigned int)32) - (unsigned int)97) + goto _LOR; + else + if ((unsigned int)1 == a >> 7) { + _LOR: ; + if (i < (unsigned int)64) { + unsigned int tmp_7; + tmp_7 = i; + i ++; + t[tmp_7] = a; + tmp_8 = 0; + } + else tmp_8 = 1; + } + else tmp_8 = 1; + j = (unsigned int)tmp_8; + } + __retres = 0; + return __retres; +} + + diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog.parse/metrics.log b/ioccc/.frama-c/2020_kurdyukov3_prog.parse/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..afbaa4d63ccd09a7e76e03b11f47830c4956046b --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog.parse/metrics.log @@ -0,0 +1,34 @@ +[metrics] Defined functions (1) +===================== + main (0 call); + +Specified-only functions (0) +============================ + + +Undefined and unspecified functions (0) +======================================= + + +'Extern' global variables (0) +============================= + + +Potential entry points (1) +========================== + main; + +Global metrics +============== +Sloc = 59 +Decision point = 10 +Global variables = 0 +If = 10 +Loop = 1 +Goto = 2 +Assignment = 28 +Exit point = 1 +Function = 1 +Function call = 5 +Pointer dereferencing = 0 +Cyclomatic complexity = 11 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog.parse/warnings.log b/ioccc/.frama-c/2020_kurdyukov3_prog.parse/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_extra.eva/alarms.csv b/ioccc/.frama-c/2020_kurdyukov3_prog_extra.eva/alarms.csv new file mode 100644 index 0000000000000000000000000000000000000000..c577fed7d0e7de012173251846de222514479f45 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog_extra.eva/alarms.csv @@ -0,0 +1,6 @@ +directory file line function property kind status property +2020/kurdyukov3 prog.extra.c 13 main initialization Unknown \initialized(&a) +2020/kurdyukov3 prog.extra.c 14 main initialization Unknown \initialized(&a) +2020/kurdyukov3 prog.extra.c 14 main initialization Unknown \initialized(&t[j]) +2020/kurdyukov3 prog.extra.c 15 main initialization Unknown \initialized(&t[i]) +2020/kurdyukov3 prog.extra.c 15 main index_bound Unknown i < 256 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_extra.eva/metrics.log b/ioccc/.frama-c/2020_kurdyukov3_prog_extra.eva/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..4a0cb35efdc4b57f7ce1591f5aa2959f0bab58c3 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog_extra.eva/metrics.log @@ -0,0 +1,9 @@ +[metrics] Eva coverage statistics +======================= +Syntactically reachable functions = 1 (out of 1) +Semantically reached functions = 1 +Coverage estimation = 100.0% +[metrics] Statements analyzed by Eva +-------------------------- +53 stmts in analyzed functions, 53 stmts analyzed (100.0%) +main: 53 stmts out of 53 (100.0%) diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_extra.eva/nonterm.log b/ioccc/.frama-c/2020_kurdyukov3_prog_extra.eva/nonterm.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_extra.eva/warnings.log b/ioccc/.frama-c/2020_kurdyukov3_prog_extra.eva/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_extra.parse/framac.ast b/ioccc/.frama-c/2020_kurdyukov3_prog_extra.parse/framac.ast new file mode 100644 index 0000000000000000000000000000000000000000..e36e3e417b012d478356b5b49ac4c1c0333fa287 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog_extra.parse/framac.ast @@ -0,0 +1,77 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "signal.h" +#include "stdarg.h" +#include "stdio.h" +#include "stdlib.h" +#include "time.h" +int main(void) +{ + int __retres; + unsigned int a; + unsigned int t[256]; + time_t tmp; + unsigned int i = (unsigned int)1; + unsigned int j = (unsigned int)0; + tmp = time((time_t *)0); + srand((unsigned int)tmp); + while (i) + if (j) { + unsigned int tmp_2; + i --; + if (i) goto _LOR; + else + if (~ a >> 8) { + unsigned int tmp_0; + unsigned int tmp_1; + _LOR: + { + if (i) tmp_0 = t[j]; else tmp_0 = a; + putchar((int)tmp_0); + tmp_1 = i; + i ++; + } + tmp_2 = tmp_1; + } + else tmp_2 = (unsigned int)0; + if (tmp_2) { + i --; + t[j] = t[i]; + if (i > (unsigned int)2) { + int tmp_3; + tmp_3 = rand(); + j = (unsigned int)tmp_3 % (i - (unsigned int)2) + (unsigned int)2; + } + else j = (unsigned int)1; + } + else { + j --; + unsigned int tmp_4 = j; + } + } + else { + int tmp_4_0; + tmp_4_0 = getchar(); + a = (unsigned int)tmp_4_0; + if ((unsigned int)1 == a >> 7) goto _LOR_0; + else + if ((unsigned int)26 > (a | (unsigned int)32) - (unsigned int)97) { + _LOR_0: ; + if ((unsigned int)256 > i) { + unsigned int tmp_5; + tmp_5 = i; + i ++; + t[tmp_5] = a; + } + else goto _LAND; + } + else { + _LAND: j ++; + unsigned int tmp_6 = j; + } + } + __retres = 0; + return __retres; +} + + diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_extra.parse/metrics.log b/ioccc/.frama-c/2020_kurdyukov3_prog_extra.parse/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..45cccee3a15a469e4db93d92780097fc1afbea0a --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog_extra.parse/metrics.log @@ -0,0 +1,34 @@ +[metrics] Defined functions (1) +===================== + main (0 call); + +Specified-only functions (0) +============================ + + +Undefined and unspecified functions (0) +======================================= + + +'Extern' global variables (0) +============================= + + +Potential entry points (1) +========================== + main; + +Global metrics +============== +Sloc = 53 +Decision point = 10 +Global variables = 0 +If = 10 +Loop = 1 +Goto = 3 +Assignment = 25 +Exit point = 1 +Function = 1 +Function call = 5 +Pointer dereferencing = 0 +Cyclomatic complexity = 11 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_extra.parse/warnings.log b/ioccc/.frama-c/2020_kurdyukov3_prog_extra.parse/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_orig.eva/alarms.csv b/ioccc/.frama-c/2020_kurdyukov3_prog_orig.eva/alarms.csv new file mode 100644 index 0000000000000000000000000000000000000000..0f08cef9cec925e750d9df704c30b19a788ed79d --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog_orig.eva/alarms.csv @@ -0,0 +1,6 @@ +directory file line function property kind status property +2020/kurdyukov3 prog.orig.c 15 main index_bound Unknown tmp_0 < 64 +2020/kurdyukov3 prog.orig.c 15 main initialization Unknown \initialized(&t[j]) +2020/kurdyukov3 prog.orig.c 15 main index_bound Unknown j < 64 +2020/kurdyukov3 prog.orig.c 15 main initialization Unknown \initialized(&t[tmp_4]) +2020/kurdyukov3 prog.orig.c 15 main index_bound Unknown tmp_4 < 64 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_orig.eva/metrics.log b/ioccc/.frama-c/2020_kurdyukov3_prog_orig.eva/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..eb80a27f1211c708ff6379bf000bfeed1efc7104 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog_orig.eva/metrics.log @@ -0,0 +1,9 @@ +[metrics] Eva coverage statistics +======================= +Syntactically reachable functions = 1 (out of 1) +Semantically reached functions = 1 +Coverage estimation = 100.0% +[metrics] Statements analyzed by Eva +-------------------------- +45 stmts in analyzed functions, 45 stmts analyzed (100.0%) +main: 45 stmts out of 45 (100.0%) diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_orig.eva/nonterm.log b/ioccc/.frama-c/2020_kurdyukov3_prog_orig.eva/nonterm.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_orig.eva/warnings.log b/ioccc/.frama-c/2020_kurdyukov3_prog_orig.eva/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_orig.parse/framac.ast b/ioccc/.frama-c/2020_kurdyukov3_prog_orig.parse/framac.ast new file mode 100644 index 0000000000000000000000000000000000000000..788d1e1c8881f9bf6a25e4b24538f5478ff34973 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog_orig.parse/framac.ast @@ -0,0 +1,59 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "signal.h" +#include "stdarg.h" +#include "stdio.h" +#include "stdlib.h" +#include "time.h" +int main(void) +{ + int __retres; + unsigned int i; + unsigned int j; + unsigned int t[64]; + time_t tmp; + unsigned int a = (unsigned int)0; + tmp = time((time_t *)0); + srand((unsigned int)tmp); + while (~ a >> 8) { + j = (unsigned int)0; + i = j; + while (1) { + int tmp_1; + int tmp_2; + unsigned int tmp_0; + tmp_1 = getchar(); + a = (unsigned int)tmp_1; + if (~ i >> 6) + if (a >> 7 == (unsigned int)1) tmp_2 = 1; + else + if ((a | (unsigned int)32) - (unsigned int)97 < (unsigned int)26) + tmp_2 = 1; + else tmp_2 = 0; + else tmp_2 = 0; + if (! tmp_2) break; + tmp_0 = i; + i ++; + t[tmp_0] = a; + } + i --; + while (i + (unsigned int)1) { + unsigned int tmp_4; + putchar((int)t[j]); + tmp_4 = i; + i --; + t[j] = t[tmp_4]; + if (i) { + int tmp_3; + tmp_3 = rand(); + j = (unsigned int)tmp_3 % i + (unsigned int)1; + } + else j = (unsigned int)0; + } + if (! (a >> 8)) putchar((int)a); + } + __retres = 0; + return __retres; +} + + diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_orig.parse/metrics.log b/ioccc/.frama-c/2020_kurdyukov3_prog_orig.parse/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..ac555d1202cf0390738363b81f4ef3a11c5a9b99 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov3_prog_orig.parse/metrics.log @@ -0,0 +1,34 @@ +[metrics] Defined functions (1) +===================== + main (0 call); + +Specified-only functions (0) +============================ + + +Undefined and unspecified functions (0) +======================================= + + +'Extern' global variables (0) +============================= + + +Potential entry points (1) +========================== + main; + +Global metrics +============== +Sloc = 45 +Decision point = 8 +Global variables = 0 +If = 8 +Loop = 3 +Goto = 0 +Assignment = 21 +Exit point = 1 +Function = 1 +Function call = 6 +Pointer dereferencing = 0 +Cyclomatic complexity = 9 diff --git a/ioccc/.frama-c/2020_kurdyukov3_prog_orig.parse/warnings.log b/ioccc/.frama-c/2020_kurdyukov3_prog_orig.parse/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov4_prog.eva/alarms.csv b/ioccc/.frama-c/2020_kurdyukov4_prog.eva/alarms.csv new file mode 100644 index 0000000000000000000000000000000000000000..3914e144860e7cc03cd8d351e087085e2a8f9e2f --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov4_prog.eva/alarms.csv @@ -0,0 +1,4 @@ +directory file line function property kind status property +2020/kurdyukov4 prog.c 9 main signed_overflow Unknown c + 1 ≤ 2147483647 +2020/kurdyukov4 prog.c 9 main mem_access Invalid or unreachable \valid_read(V + 2) +FRAMAC_SHARE/libc stdlib.h 78 atoi precondition Unknown valid_nptr: \valid_read(nptr) diff --git a/ioccc/.frama-c/2020_kurdyukov4_prog.eva/metrics.log b/ioccc/.frama-c/2020_kurdyukov4_prog.eva/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..3fb356d1d301cd2f188e72c09099979bce8bc552 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov4_prog.eva/metrics.log @@ -0,0 +1,9 @@ +[metrics] Eva coverage statistics +======================= +Syntactically reachable functions = 1 (out of 1) +Semantically reached functions = 1 +Coverage estimation = 100.0% +[metrics] Statements analyzed by Eva +-------------------------- +190 stmts in analyzed functions, 12 stmts analyzed (6.3%) +main: 12 stmts out of 190 (6.3%) diff --git a/ioccc/.frama-c/2020_kurdyukov4_prog.eva/nonterm.log b/ioccc/.frama-c/2020_kurdyukov4_prog.eva/nonterm.log new file mode 100644 index 0000000000000000000000000000000000000000..860d934d17bb5bfe81cd6f6874299eaa3edc7cb4 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov4_prog.eva/nonterm.log @@ -0,0 +1,2 @@ +2020/kurdyukov4/prog.c:9:[nonterm] warning: non-terminating function call +stack: main diff --git a/ioccc/.frama-c/2020_kurdyukov4_prog.eva/warnings.log b/ioccc/.frama-c/2020_kurdyukov4_prog.eva/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_kurdyukov4_prog.parse/framac.ast b/ioccc/.frama-c/2020_kurdyukov4_prog.parse/framac.ast new file mode 100644 index 0000000000000000000000000000000000000000..14ac2c8511cdcd55a979fdaec3e2f0cf79474c08 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov4_prog.parse/framac.ast @@ -0,0 +1,220 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "stdarg.h" +#include "stddef.h" +#include "stdint.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "strings.h" +int main(int c, char **V) +{ + int __retres; + int k; + int l; + int p; + int i; + int x; + int y; + int n; + int q; + uint64_t s; + uint64_t z; + uint32_t *h; + uint32_t a; + uint32_t t[512]; + uint64_t S = (unsigned long)5; + while (1) { + int tmp_14; + tmp_14 = c; + c ++; + ; + if (! (tmp_14 == 5)) break; + { + uint8_t *m; + void *F; + int tmp; + x = atoi((char const *)*(V + 2)); + y = atoi((char const *)*(V + 3)); + tmp = atoi((char const *)*(V + 4)); + s = (unsigned long)tmp; + if (x >> 20) break; + else + if ((y - 1) >> 7) break; + else { + q = 1; + ; + F = (void *)fopen((char const *)*(V + q),"rb"); + if (F) { + int tmp_0; + tmp_0 = fseek((FILE *)F,(long)0,2); + if (tmp_0) break; + else { + long tmp_1; + tmp_1 = ftell((FILE *)F); + n = (int)tmp_1; + ; + if (y > n) break; + else { + int tmp_2; + tmp_2 = fseek((FILE *)F,(long)0,0); + if (tmp_2) break; + else { + m = (uint8_t *)malloc((unsigned long)(n + y)); + if (m) { + size_t tmp_3; + tmp_3 = fread((void *)m,(unsigned long)1, + (unsigned long)n,(FILE *)F); + ; + if (tmp_3 - (size_t)n) break; + else + if (n >> 29) break; + } + else break; + } + } + } + } + else break; + } + fclose((FILE *)F); + while (S * (uint64_t)5 > S) S *= (uint64_t)5; + l = 0; + k = l; + i = k; + while (i < n) { + int tmp_6; + tmp_6 = i; + i ++; + a = (unsigned int)*(m + tmp_6); + if ((uint32_t)'_' - a) { + if (a == (uint32_t)'<') { + a = (unsigned int)' '; + while (1) + if (i < n) { + int tmp_4; + tmp_4 = i; + i ++; + ; + if (! ((int)*(m + tmp_4) - '>')) break; + } + else break; + } + if (a - (uint32_t)' ') { + if (a - (uint32_t)'\n') { + if (a - (uint32_t)'\r') { + if (a - (uint32_t)'\t') goto _LOR; else goto _LAND_1; + } + else goto _LAND_1; + } + else goto _LAND_1; + } + else { + _LAND_1: { /* sequence */ + a = (unsigned int)' '; + ; + } + if ((uint32_t)k - a) { + int tmp_5; + _LOR: + { /* sequence */ + tmp_5 = l; + l ++; + k = (int)a; + *(m + tmp_5) = (unsigned char)k; + } + } + } + } + } + n = l; + memcpy((void *)(m + l),(void const *)m,(unsigned long)y); + while (l * 3 > q) q += q; + h = (uint32_t *)malloc((unsigned long)(4 * q)); + if (h) { + int tmp_7; + tmp_7 = q; + q --; + ; + ; + memset((void *)h,-1,(unsigned long)(4 * tmp_7)); + k = 0; + while (k < l) { + int tmp_8; + i = 0; + a = (unsigned int)i; + while (i < y) { + int tmp_9; + tmp_9 = i; + i ++; + a = (a ^ (unsigned int)*(m + (k + tmp_9))) * (unsigned int)79764919; + } + while (1) { + i = (int)*(h + (a & (unsigned int)q)); + if (! (i ^ -1)) break; + a += (uint32_t)1; + } + tmp_8 = k; + k ++; + *(h + (a & (unsigned int)q)) = (unsigned int)tmp_8; + } + s *= S; + a = (unsigned int)(s >> 31); + z = (unsigned long)a; + p = (int)(z * (uint64_t)n >> 32); + while (1) { + int tmp_13; + tmp_13 = x; + x --; + ; + if (! tmp_13) break; + n = 0; + memset((void *)(t),n,(unsigned long)(8 << 8)); + i = 0; + a = (unsigned int)i; + while (i < y) { + int tmp_10; + tmp_10 = i; + i ++; + a = (a ^ (unsigned int)*(m + (p + tmp_10))) * (unsigned int)79764919; + } + while (1) { + int tmp_12; + i = (int)*(h + (a & (unsigned int)q)); + if (! (i ^ -1)) break; + tmp_12 = memcmp((void const *)(m + p),(void const *)(m + i), + (unsigned long)y); + if (! tmp_12) { + int tmp_11; + k = (int)*(m + (i + y)) * 2; + tmp_11 = k; + k ++; + t[tmp_11] += (uint32_t)1; + n ++; + t[k] = (unsigned int)i; + } + a += (uint32_t)1; + } + s *= S; + a = (unsigned int)(s >> 31); + z = (unsigned long)a; + n = (int)(z * (uint64_t)n >> 32); + k = -1; + while (n >= 0) { + k ++; + n = (int)((uint32_t)n - t[k * 2]); + } + putchar(k); + p = (int)(t[(k + k) + 1] + (uint32_t)1); + if (p - l) p = p; else p = 0; + } + putchar('\n'); + c = 0; + } + } + } + __retres = ! (! c); + return __retres; +} + + diff --git a/ioccc/.frama-c/2020_kurdyukov4_prog.parse/metrics.log b/ioccc/.frama-c/2020_kurdyukov4_prog.parse/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..851f5e670db39e3dcd4ac1305249abb699ff81e7 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov4_prog.parse/metrics.log @@ -0,0 +1,34 @@ +[metrics] Defined functions (1) +===================== + main (0 call); + +Specified-only functions (0) +============================ + + +Undefined and unspecified functions (0) +======================================= + + +'Extern' global variables (0) +============================= + + +Potential entry points (1) +========================== + main; + +Global metrics +============== +Sloc = 190 +Decision point = 32 +Global variables = 0 +If = 32 +Loop = 12 +Goto = 4 +Assignment = 79 +Exit point = 1 +Function = 1 +Function call = 17 +Pointer dereferencing = 13 +Cyclomatic complexity = 33 diff --git a/ioccc/.frama-c/2020_kurdyukov4_prog.parse/warnings.log b/ioccc/.frama-c/2020_kurdyukov4_prog.parse/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..45250a22e160be0f8cc25ee9893e39d16720ba14 --- /dev/null +++ b/ioccc/.frama-c/2020_kurdyukov4_prog.parse/warnings.log @@ -0,0 +1,5 @@ +2020/kurdyukov4/prog.c:13:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov4/prog.c:13:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov4/prog.c:14:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov4/prog.c:14:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * +2020/kurdyukov4/prog.c:15:[kernel:typing:implicit-conv-void-ptr] warning: implicit conversion from void * to FILE * diff --git a/ioccc/.frama-c/2020_otterness_prog.eva/alarms.csv b/ioccc/.frama-c/2020_otterness_prog.eva/alarms.csv new file mode 100644 index 0000000000000000000000000000000000000000..97c598d18aae876e4c86b3fbe1b4169b6b48062d --- /dev/null +++ b/ioccc/.frama-c/2020_otterness_prog.eva/alarms.csv @@ -0,0 +1,87 @@ +directory file line function property kind status property +2020/otterness prog.c 12 A initialization Unknown \initialized(c + (int)(!(c ≢ \null)? 0: 1)) +2020/otterness prog.c 12 A initialization Unknown \initialized(c) +2020/otterness prog.c 12 A mem_access Unknown \valid_read(c + (int)(!(c ≢ \null)? 0: 1)) +2020/otterness prog.c 12 A mem_access Unknown \valid_read(c) +2020/otterness prog.c 12 A ptr_comparison Unknown \pointer_comparable((void *)0, (void *)c) +2020/otterness prog.c 12 A signed_overflow Unknown (int)((unsigned short)*c) << l ≤ 2147483647 +2020/otterness prog.c 15 B mem_access Unknown \valid(tmp) +2020/otterness prog.c 15 B shift Unknown 0 ≤ l < 32 +2020/otterness prog.c 16 B mem_access Unknown \valid(c) +2020/otterness prog.c 24 C initialization Unknown \initialized(c + d) +2020/otterness prog.c 24 C mem_access Unknown \valid_read(c + d) +2020/otterness prog.c 26 C shift Unknown 0 ≤ l < 32 +2020/otterness prog.c 45 D division_by_zero Unknown (int)c ≢ 0 +2020/otterness prog.c 50 F mem_access Unknown \valid(c) +2020/otterness prog.c 51 F division_by_zero Unknown n ≢ 0 +2020/otterness prog.c 57 F mem_access Unknown \valid(c) +2020/otterness prog.c 58 F shift Unknown 0 ≤ l < 32 +2020/otterness prog.c 68 G signed_overflow Unknown (int)p << (int)q ≤ 2147483647 +2020/otterness prog.c 68 G shift Unknown 0 ≤ (int)q < 32 +2020/otterness prog.c 70 G initialization Unknown \initialized(c) +2020/otterness prog.c 70 G mem_access Unknown \valid_read(c) +2020/otterness prog.c 84 G division_by_zero Unknown (unsigned int)o ≢ 0 +2020/otterness prog.c 85 G shift Unknown 0 ≤ (int)q < 32 +2020/otterness prog.c 104 H division_by_zero Unknown n ≢ 0 +2020/otterness prog.c 105 H division_by_zero Unknown (int)m ≢ 0 +2020/otterness prog.c 106 H initialization Unknown \initialized(c + n) +2020/otterness prog.c 106 H mem_access Unknown \valid_read(c + n) +2020/otterness prog.c 107 H shift Unknown 0 ≤ (int)((int)q * (int)q) < 32 +2020/otterness prog.c 107 H shift Unknown 0 ≤ (int)q < 32 +2020/otterness prog.c 110 H ptr_comparison Unknown \pointer_comparable((void *)c, (void *)d) +2020/otterness prog.c 132 J signed_overflow Unknown (int)((int)s - (int)o) << (int)r ≤ 2147483647 +2020/otterness prog.c 132 J shift Unknown 0 ≤ (int)((int)s - (int)o) +2020/otterness prog.c 132 J shift Unknown 0 ≤ (int)r < 32 +2020/otterness prog.c 133 J division_by_zero Unknown (int)((int)s + (int)o) ≢ 0 +2020/otterness prog.c 134 J division_by_zero Unknown l ≢ 0 +2020/otterness prog.c 135 J division_by_zero Unknown (unsigned int)r ≢ 0 +2020/otterness prog.c 136 J division_by_zero Unknown n ≢ 0 +2020/otterness prog.c 140 J division_by_zero Unknown (unsigned int)m ≢ 0 +2020/otterness prog.c 147 J mem_access Unknown \valid(t + k) +2020/otterness prog.c 148 J mem_access Unknown \valid(t + r) +2020/otterness prog.c 149 J mem_access Unknown \valid(u) +2020/otterness prog.c 150 J precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n) +2020/otterness prog.c 150 J precondition of memcpy Unknown valid_src: valid_read_or_empty(src, n) +2020/otterness prog.c 166 K shift Unknown 0 ≤ (int)tmp_3 < 32 +2020/otterness prog.c 167 K division_by_zero Unknown (unsigned int)e ≢ 0 +2020/otterness prog.c 175 K mem_access Unknown \valid(b) +2020/otterness prog.c 176 K mem_access Unknown \valid(b + (int)(k ≢ 0? 0: 1)) +2020/otterness prog.c 176 K mem_access Unknown \valid_read(b) +2020/otterness prog.c 177 K mem_access Unknown \valid(b + n) +2020/otterness prog.c 178 K initialization Unknown \initialized(b + n) +2020/otterness prog.c 178 K mem_access Unknown \valid(b + o) +2020/otterness prog.c 178 K mem_access Unknown \valid_read(b + n) +2020/otterness prog.c 180 K shift Unknown 0 ≤ (unsigned int)((unsigned int)o * l) < 32 +2020/otterness prog.c 182 K mem_access Unknown \valid(tmp_8) +2020/otterness prog.c 183 K mem_access Unknown \valid(tmp_9) +2020/otterness prog.c 184 K division_by_zero Unknown (unsigned int)(n + (unsigned int)o) ≢ 0 +2020/otterness prog.c 185 K mem_access Unknown \valid(tmp_10) +2020/otterness prog.c 188 K mem_access Unknown \valid(tmp_12) +2020/otterness prog.c 189 K mem_access Unknown \valid(d) +2020/otterness prog.c 191 K mem_access Unknown \valid(tmp_13) +2020/otterness prog.c 192 K mem_access Unknown \valid(tmp_15) +2020/otterness prog.c 193 K precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n) +2020/otterness prog.c 193 K precondition of memcpy Unknown valid_src: valid_read_or_empty(src, n) +2020/otterness prog.c 196 K division_by_zero Unknown (int)s ≢ 0 +2020/otterness prog.c 198 K mem_access Unknown \valid(tmp_16) +2020/otterness prog.c 199 K mem_access Unknown \valid(tmp_17) +2020/otterness prog.c 200 K mem_access Unknown \valid(tmp_18) +2020/otterness prog.c 201 K mem_access Unknown \valid(d) +2020/otterness prog.c 202 K mem_access Unknown \valid(c + (unsigned int)(l + (unsigned int)p)) +2020/otterness prog.c 204 K precondition of fwrite Unknown valid_ptr_block: \valid_read((char *)ptr + (0 .. nmemb * size - 1)) +2020/otterness prog.c 204 K precondition of fwrite Unknown valid_stream: \valid(stream) +2020/otterness prog.c 205 K precondition of fwrite Unknown valid_ptr_block: \valid_read((char *)ptr + (0 .. nmemb * size - 1)) +2020/otterness prog.c 205 K precondition of fwrite Unknown valid_stream: \valid(stream) +2020/otterness prog.c 219 main precondition of fread Unknown valid_ptr_block: \valid((char *)ptr + (0 .. nmemb * size - 1)) +2020/otterness prog.c 219 main precondition of fread Unknown valid_stream: \valid(stream) +2020/otterness prog.c 221 main division_by_zero Unknown n ≢ 0 +2020/otterness prog.c 222 main initialization Unknown \initialized(c + n) +2020/otterness prog.c 222 main mem_access Unknown \valid_read(c + n) +2020/otterness prog.c 222 main initialization Unknown \initialized(c + (unsigned int)((unsigned int)m - k)) +2020/otterness prog.c 222 main mem_access Unknown \valid_read(c + (unsigned int)((unsigned int)m - k)) +FRAMAC_SHARE/libc stdio.h 351 fread precondition Unknown valid_ptr_block: \valid((char *)ptr + (0 .. nmemb * size - 1)) +FRAMAC_SHARE/libc stdio.h 352 fread precondition Unknown valid_stream: \valid(stream) +FRAMAC_SHARE/libc stdio.h 364 fwrite precondition Unknown valid_ptr_block: \valid_read((char *)ptr + (0 .. nmemb * size - 1)) +FRAMAC_SHARE/libc stdio.h 365 fwrite precondition Unknown valid_stream: \valid(stream) +FRAMAC_SHARE/libc string.h 92 memcpy precondition Unknown valid_dest: valid_or_empty(dest, n) +FRAMAC_SHARE/libc string.h 93 memcpy precondition Unknown valid_src: valid_read_or_empty(src, n) diff --git a/ioccc/.frama-c/2020_otterness_prog.eva/metrics.log b/ioccc/.frama-c/2020_otterness_prog.eva/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..b0908b6df2cf9d8416675afb5a3c347d0c62feb7 --- /dev/null +++ b/ioccc/.frama-c/2020_otterness_prog.eva/metrics.log @@ -0,0 +1,19 @@ +[metrics] Eva coverage statistics +======================= +Syntactically reachable functions = 11 (out of 11) +Semantically reached functions = 11 +Coverage estimation = 100.0% +[metrics] Statements analyzed by Eva +-------------------------- +328 stmts in analyzed functions, 324 stmts analyzed (98.8%) +A: 2 stmts out of 2 (100.0%) +B: 6 stmts out of 6 (100.0%) +D: 17 stmts out of 17 (100.0%) +G: 47 stmts out of 47 (100.0%) +H: 26 stmts out of 26 (100.0%) +I: 11 stmts out of 11 (100.0%) +J: 22 stmts out of 22 (100.0%) +K: 122 stmts out of 122 (100.0%) +main: 22 stmts out of 22 (100.0%) +C: 28 stmts out of 29 (96.6%) +F: 21 stmts out of 24 (87.5%) diff --git a/ioccc/.frama-c/2020_otterness_prog.eva/nonterm.log b/ioccc/.frama-c/2020_otterness_prog.eva/nonterm.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_otterness_prog.eva/warnings.log b/ioccc/.frama-c/2020_otterness_prog.eva/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/2020_otterness_prog.parse/framac.ast b/ioccc/.frama-c/2020_otterness_prog.parse/framac.ast new file mode 100644 index 0000000000000000000000000000000000000000..f4a8ea32f3c0590b6fbb26a75b46468ba43dfa99 --- /dev/null +++ b/ioccc/.frama-c/2020_otterness_prog.parse/framac.ast @@ -0,0 +1,411 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "stdarg.h" +#include "stddef.h" +#include "stdint.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "strings.h" +typedef uint8_t u1; +typedef uint16_t u2; +typedef uint32_t u4; +u4 k; +u4 l; +u4 n; +u1 m; +u1 o; +u1 p; +u1 q; +u1 r; +u1 s; +u1 *t; +u1 *u; +u2 A(u1 *c) +{ + u2 __retres; + __retres = (unsigned short)((int)*(c + ! (! c)) | ((int)((unsigned short)*c) << l)); + return __retres; +} + +void B(u1 *c, u2 a) +{ + u1 *tmp; + tmp = c; + c ++; + *tmp = (unsigned char)((int)a >> l); + *c = (unsigned char)a; + return; +} + +int C(u1 *c, u4 *a) +{ + int __retres; + u1 b; + u4 tmp; + u4 tmp_0; + u1 d = (unsigned char)k; + tmp = l; + l -= (u4)1; + s = (unsigned char)tmp; + tmp_0 = k; + k += (u4)1; + *a = tmp_0; + while ((int)d < (int)s >> k) { + b = *(c + d); + *a |= (unsigned int)((int)b & (int)p); + if (! ((int)b >> l)) { + u4 tmp_1; + tmp_1 = k; + k -= (u4)1; + d = (unsigned char)((u4)d + tmp_1); + l = (unsigned int)s; + __retres = (int)d; + goto return_label; + } + *a <<= l; + d = (unsigned char)((int)d + 1); + } + exit(! k); + __retres = (int)p; + return_label: return __retres; +} + +u1 D(u4 a) +{ + u1 __retres; + u4 tmp; + tmp = k; + k += (u4)1; + u1 b = (unsigned char)tmp; + u1 c = (unsigned char)(l - k); + if (a) { + b = (unsigned char)k; + while (1) { + a >>= k; + if (! a) break; + b = (unsigned char)((int)b + 1); + } + } + if (k) k = (unsigned int)(! k); else k = k; + __retres = (unsigned char)((int)b / (int)c + ! (! ((int)b % (int)c))); + return __retres; +} + +int F(u4 a, u1 *c) +{ + int __retres; + u4 tmp_0; + u1 b = D(a); + tmp_0 = l; + l -= (u4)1; + *c = (unsigned char)((u4)s - tmp_0); + r = (unsigned char)((u4)q / n); + if (! a) { + __retres = (int)b; + goto return_label; + } + if ((int)b > (int)r) exit((int)o); + c += (int)b; + c --; + while (a) { + *c = (unsigned char)(a & (unsigned int)p); + a >>= l; + c --; + } + l = (unsigned int)s; + __retres = (int)b; + return_label: return __retres; +} + +u1 *G(u1 *c, u1 *a) +{ + u1 *__retres; + u4 d; + u1 b; + u1 e; + if ((int)m < (int)p) m = (unsigned char)((int)p << (int)q); else m = m; + if ((u4)q < n + (u4)o) q = (unsigned char)((int)p >> (int)q); else + q = q; + e = *c; + if ((int)e == (int)m) goto _LOR; + else + if ((int)e == (int)m + (int)q) { + _LOR: + { + int tmp; + *a = (unsigned char)k; + c ++; + tmp = C(c,& d); + c += tmp; + __retres = c + d; + goto return_label; + } + } + if ((int)e == ((int)m | (int)p)) { + int tmp_0; + *a = (unsigned char)k; + c ++; + c ++; + tmp_0 = C(c,& d); + c += tmp_0; + __retres = c + d; + goto return_label; + } + l /= (u4)o; + if ((int)e >> (int)q) { + b = *c; + c ++; + *a = b; + } + else b = *a; + e = (unsigned char)((int)b >> l); + if ((int)e < (int)s) exit((int)n); + else + if ((u4)e > l + (u4)s) exit((int)n); + if ((u4)e != l + (u4)s) + if ((u4)e != l + (u4)o) c ++; + c ++; + l = (unsigned int)s; + __retres = c; + return_label: return __retres; +} + +u1 *H(u1 *c, u4 *a) +{ + u4 b; + u4 e; + u1 *d; + u2 tmp; + u2 tmp_0; + u4 h = (unsigned int)q; + u4 i = (unsigned int)m; + u1 f = (unsigned char)k; + *a = k; + q = (unsigned char)((u4)q / n); + m = (unsigned char)(((int)p - (int)m) + (int)p / (int)m); + if ((int)*(c + n) != (int)m) exit((int)q); + tmp = A(c + (int)q); + tmp_0 = A(c + ((int)m >> (int)q)); + b = ((unsigned int)tmp << (int)q * (int)q) | (unsigned int)tmp_0; + c += l; + d = c + b; + while (c < d) { + int tmp_1; + tmp_1 = C(c,& e); + c += tmp_1; + *a += e; + c = G(c,& f); + } + q = (unsigned char)h; + m = (unsigned char)i; + return c; +} + +u4 I(u1 *c, u4 a) +{ + u4 e; + u4 b; + u4 d = k; + e = k; + while (e < a) { + c = H(c,& b); + if (b > d) d = b; + e += (u4)1; + } + return d; +} + +u1 *J(u1 *c, u4 a, u4 b) +{ + u1 *__retres; + u1 d; + u1 e; + if (l > (u4)o) { + s = (unsigned char)((int)s - 1); + o = (unsigned char)(((int)s - (int)o) << (int)r); + l = (unsigned int)((int)p % ((int)s + (int)o)); + r = (unsigned char)((u4)o / l); + n = l / (u4)r; + m = (unsigned char)((u4)o / n); + } + d = (unsigned char)(l + (u4)r); + e = o; + if (! (a % (unsigned int)m)) { + d = (unsigned char)(l - (u4)m); + e = (unsigned char)((u4)o + l); + } + else + if (a % (unsigned int)m == (unsigned int)r) { + d = (unsigned char)l; + e = (unsigned char)(n + (u4)o); + } + *(t + k) = d; + *(t + r) = e; + *u = d; + memcpy((void *)c,(void const *)t,(unsigned long)b); + __retres = c + b; + return __retres; +} + +void K(u1 *c, u4 a) +{ + u1 *b; + u1 *d; + u2 e; + u2 f; + u4 g; + u4 h; + u4 i; + u4 j; + u2 tmp; + u4 tmp_0; + u4 tmp_1; + u4 tmp_2; + u1 tmp_3; + u4 tmp_5; + u1 tmp_4; + u1 tmp_6; + u1 tmp_7; + u1 *tmp_8; + u1 *tmp_9; + u1 *tmp_10; + int tmp_11; + u1 *tmp_12; + u1 *tmp_13; + u4 tmp_14; + u1 *tmp_15; + u1 *tmp_16; + u1 *tmp_17; + u1 *tmp_18; + u4 tmp_19; + o = (unsigned char)(n ^ k); + m = (unsigned char)l; + l = (unsigned int)((int)o << (int)o); + f = A((c + l) + (int)o); + tmp = A(((c + l) + (int)o) + (int)o); + tmp_0 = k; + k -= (u4)1; + e = (unsigned short)((int)tmp >> tmp_0); + tmp_1 = k; + k += (u4)1; + p = (unsigned char)(~ tmp_1); + tmp_2 = k; + k -= (u4)1; + p = (unsigned char)((int)p >> tmp_2); + q = (unsigned char)((int)p >> n); + tmp_3 = q; + q = (unsigned char)((int)q - 1); + ; + if ((int)e >> (int)tmp_3) exit((int)(n + (u4)o)); + ; + tmp_4 = q; + q = (unsigned char)((int)q - 1); + ; + tmp_5 = I(c + (int)tmp_4,(unsigned int)f); + g = tmp_5 / (u4)e; + tmp_6 = D((unsigned int)e); + i = (n + (u4)o) + (u4)tmp_6; + t = (u1 *)malloc((unsigned long)i); + if (! t) exit((int)(n * (u4)o)); + j = g * i + (u4)q; + b = (u1 *)malloc((unsigned long)j); + l -= (u4)1; + r = (unsigned char)l; + l += (u4)1; + if (! b) exit((int)r); + *b = (unsigned char)((l << n) | (unsigned int)q); + *(b + ! k) = (unsigned char)((int)*b + (int)r); + *(b + n) = (unsigned char)((u4)((int)*b << n) + n); + tmp_7 = r; + r = (unsigned char)((int)r - 1); + *(b + o) = (unsigned char)((int)*(b + n) + (int)tmp_7); + B(b + n * (u4)o,(unsigned short)(j - l)); + B(b + (int)o * (int)o,(unsigned short)((j - l) >> (u4)o * l)); + d = t; + tmp_8 = d; + d ++; + *tmp_8 = (unsigned char)k; + tmp_9 = d; + d ++; + *tmp_9 = (unsigned char)((int)r * (int)r); + m = (unsigned char)((u4)p / (n + (u4)o)); + tmp_10 = d; + d ++; + *tmp_10 = (unsigned char)(((int)p - (int)m) - (int)o); + tmp_11 = F((unsigned int)e,d); + d += tmp_11; + u = d; + tmp_12 = d; + d ++; + *tmp_12 = (unsigned char)((int)r * (int)r); + *d = (unsigned char)k; + d = b + l; + tmp_13 = d; + d ++; + tmp_14 = k; + k += (u4)1; + *tmp_13 = (unsigned char)tmp_14; + tmp_15 = d; + d ++; + *tmp_15 = (unsigned char)(((int)p + (int)q) + (int)q); + memcpy((void *)d,(void const *)(t + k),(unsigned long)(i - k)); + d += i - k; + h = k; + while (h < g) { + d = J(d,h,i); + h += (u4)1; + } + l = (unsigned int)(((int)o + (int)m) / (int)s - (int)m); + o = r; + tmp_16 = d; + d ++; + k -= (u4)1; + *tmp_16 = (unsigned char)k; + tmp_17 = d; + d ++; + *tmp_17 = (unsigned char)(~ k); + tmp_18 = d; + d ++; + *tmp_18 = (unsigned char)((u4)((int)p / (int)o) - (u4)o * l); + tmp_19 = k; + k += (u4)1; + *d = (unsigned char)tmp_19; + *(c + (l + (u4)p)) = (unsigned char)k; + B((c + l) + (int)o,(unsigned short)((u4)f + k)); + fwrite((void const *)c,(unsigned long)a,(unsigned long)(! (! c)), + __fc_stdout); + fwrite((void const *)b,(unsigned long)j,(unsigned long)(! (! b)), + __fc_stdout); + return; +} + +int main(void) +{ + int __retres; + u4 a; + u4 b; + u1 *c; + size_t tmp; + k = (unsigned int)(! (! __fc_stdin)); + n = (k + k) + k; + l = k << n; + m = (unsigned char)l; + l = (l | (l >> (k + k))) << k; + b = k << l; + c = (u1 *)malloc((unsigned long)b); + if (! c) exit((int)m); + tmp = fread((void *)c,(unsigned long)k,(unsigned long)b,__fc_stdin); + a = (unsigned int)tmp; + l = (u4)(((int)m << k) + (int)m) + k; + if (a >= b) exit((int)(l / n + k)); + if ((u4)*(c + n) != l << (k + k)) exit((int)((u4)((int)m << k) - (n << k))); + else + if ((u4)*(c + ((u4)m - k)) != n + n) exit((int)((u4)((int)m << k) - ( + n << k))); + K(c,a); + __retres = ! b; + return __retres; +} + + diff --git a/ioccc/.frama-c/2020_otterness_prog.parse/metrics.log b/ioccc/.frama-c/2020_otterness_prog.parse/metrics.log new file mode 100644 index 0000000000000000000000000000000000000000..c06a131a00668d197682794ca77d4a6aff2d8bf6 --- /dev/null +++ b/ioccc/.frama-c/2020_otterness_prog.parse/metrics.log @@ -0,0 +1,35 @@ +[metrics] Defined functions (11) +====================== + A (4 calls); B (3 calls); C (3 calls); D (2 calls); F (1 call); G (1 call); + H (1 call); I (1 call); J (1 call); K (1 call); main (0 call); + +Specified-only functions (0) +============================ + + +Undefined and unspecified functions (0) +======================================= + + +'Extern' global variables (0) +============================= + + +Potential entry points (1) +========================== + main; + +Global metrics +============== +Sloc = 328 +Decision point = 33 +Global variables = 11 +If = 33 +Loop = 6 +Goto = 5 +Assignment = 202 +Exit point = 11 +Function = 11 +Function call = 38 +Pointer dereferencing = 46 +Cyclomatic complexity = 44 diff --git a/ioccc/.frama-c/2020_otterness_prog.parse/warnings.log b/ioccc/.frama-c/2020_otterness_prog.parse/warnings.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ioccc/.frama-c/GNUmakefile b/ioccc/.frama-c/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..3d1856bf0761aa95db4d54a5b2e9e3bb198bed20 --- /dev/null +++ b/ioccc/.frama-c/GNUmakefile @@ -0,0 +1,140 @@ +# Makefile template for Frama-C/Eva case studies. +# For details and usage information, see the Frama-C User Manual. + +### Prologue. Do not modify this block. ####################################### +-include path.mk +FRAMAC ?= frama-c +include $(shell $(FRAMAC)-config -print-share-path)/analysis-scripts/prologue.mk +############################################################################### + +# Edit below as needed. MACHDEP is mandatory. Suggested flags are optional. + +MACHDEP = x86_64 + +## Preprocessing flags (for -cpp-extra-args) +CPPFLAGS += \ + +## General flags +FCFLAGS += \ + -add-symbolic-path=..:. \ + -kernel-warn-key annot:missing-spec=abort \ + -kernel-warn-key typing:implicit-function-declaration=abort \ + +## Eva-specific flags +EVAFLAGS += \ + -eva-warn-key builtins:missing-spec=abort \ + +## GUI-only flags +FCGUIFLAGS += \ + +## Analysis targets (suffixed with .eva) +TARGETS = \ +2020_burton_prog.eva \ +2020_giles_prog.eva \ +2020_kurdyukov1_prog.eva \ +2020_kurdyukov1_prog_extra.eva \ +2020_kurdyukov1_prog_orig.eva \ +2020_kurdyukov2_prog_ppm.eva \ +2020_kurdyukov3_prog.eva \ +2020_kurdyukov3_prog_extra.eva \ +2020_kurdyukov3_prog_orig.eva \ +2020_kurdyukov4_prog.eva \ +2020_otterness_prog.eva \ + +#### The folowing cases are not currently handled by Frama-C; +#### See comments in .parse lines + +NOT_HANDLED=\ +2020_carlini_prog.eva \ +2020_endoh1_prog.eva \ +2020_endoh1_prog_orig.eva \ +2020_endoh2_prog.eva \ +2020_endoh3_clock.eva \ +2020_endoh3_prog.eva \ +2020_endoh3_prog_alt.eva \ +2020_ferguson1_termcaps.eva \ +2020_ferguson1_prog_3.eva \ +2020_ferguson1_prog.eva \ +2020_ferguson1_prog_2.eva \ +2020_ferguson1_prog_alt.eva \ +2020_ferguson1_prog_3-j.eva \ +2020_ferguson2_prog.eva \ +2020_ferguson2_recode.eva \ +2020_kurdyukov2_prog.eva \ +2020_kurdyukov2_prog_png.eva \ +2020_kurdyukov4_rand.eva \ +2020_tsoj_prog.eva \ +2020_yang_prog.eva \ + +### Each target <t>.eva needs a rule <t>.parse with source files as prerequisites + +2020_burton_prog.parse: ../2020/burton/prog.c +2020_burton_prog.parse: FCFLAGS += -json-compilation-database ../2020/burton \ + +#2020_carlini_prog.parse: ../2020/carlini/prog.c # missing spec for scanf with non-static format argument +#2020_carlini_prog.parse: FCFLAGS += -json-compilation-database ../2020/carlini \ + +#2020_endoh1_prog.parse: ../2020/endoh1/prog.c # requires <ncurses.h> + +#2020_endoh1_prog_orig.parse: ../2020/endoh1/prog_orig.c # requires <ncurses.h> + +#2020_endoh2_prog.parse: ../2020/endoh2/prog.c # requires <complex.h> + +#2020_endoh3_clock.parse: ../2020/endoh3/clock.c # parsing issue with comment/slash + +#2020_endoh3_prog.parse: ../2020/endoh3/prog.c # parsing issue with comment/slash + +#2020_endoh3_prog_alt.parse: ../2020/endoh3/prog_alt.c # parsing issue with comment/slash + +#2020_ferguson1_termcaps.parse: ../2020/ferguson1/termcaps.c # requires <curses.h> + +#2020_ferguson1_prog_3.parse: ../2020/ferguson1/prog.3.c # requires <curses.h> + +#2020_ferguson1_prog.parse: ../2020/ferguson1/prog.c # requires <curses.h> + +#2020_ferguson1_prog_2.parse: ../2020/ferguson1/prog.2.c # requires <curses.h> + +#2020_ferguson1_prog_alt.parse: ../2020/ferguson1/prog.alt.c # requires <curses.h> + +#2020_ferguson1_prog_3-j.parse: ../2020/ferguson1/prog.3-j.c # requires <curses.h> + +#2020_ferguson2_prog.parse: ../2020/ferguson2/prog.c # missing spec for stdio.h's getdelim + +#2020_ferguson2_recode.parse: ../2020/ferguson2/recode.c # missing spec for stdio.h's getdelim + +2020_giles_prog.parse: ../2020/giles/prog.c + +2020_kurdyukov1_prog.parse: ../2020/kurdyukov1/prog.c + +2020_kurdyukov1_prog_extra.parse: ../2020/kurdyukov1/prog.extra.c + +2020_kurdyukov1_prog_orig.parse: ../2020/kurdyukov1/prog.orig.c + +2020_kurdyukov2_prog_ppm.parse: ../2020/kurdyukov2/prog.ppm.c + +#2020_kurdyukov2_prog.parse: ../2020/kurdyukov2/prog.c # requires <jpeglib.h> + +#2020_kurdyukov2_prog_png.parse: ../2020/kurdyukov2/prog.png.c # requires <png.h> + +2020_kurdyukov3_prog.parse: ../2020/kurdyukov3/prog.c + +2020_kurdyukov3_prog_extra.parse: ../2020/kurdyukov3/prog.extra.c + +2020_kurdyukov3_prog_orig.parse: ../2020/kurdyukov3/prog.orig.c + +2020_kurdyukov4_prog.parse: ../2020/kurdyukov4/prog.c + +#2020_kurdyukov4_rand.parse: ../2020/kurdyukov4/rand.c # missing spec for stdlib.h's memmem + +2020_otterness_prog.parse: ../2020/otterness/prog.c + +#2020_tsoj_prog.parse: ../2020/tsoj/prog.c # missing macro TIOCGWINSZ (ioctl) + +#2020_yang_prog.parse: ../2020/yang/prog.c # missing spec for printf with non-static format argument + +### Epilogue. Do not modify this block. ####################################### +include $(shell $(FRAMAC)-config -print-share-path)/analysis-scripts/epilogue.mk +############################################################################### + +# optional, for OSCS +-include ../../Makefile.common diff --git a/ioccc/.frama-c/path.mk b/ioccc/.frama-c/path.mk new file mode 120000 index 0000000000000000000000000000000000000000..57620d6d4816c69648f7a48a2ab302665cd5ac66 --- /dev/null +++ b/ioccc/.frama-c/path.mk @@ -0,0 +1 @@ +../../path.mk \ No newline at end of file diff --git a/ioccc/.frama-c/stubs.c b/ioccc/.frama-c/stubs.c new file mode 100644 index 0000000000000000000000000000000000000000..fad866f2160ba5533c8658794a520c2bf0880962 --- /dev/null +++ b/ioccc/.frama-c/stubs.c @@ -0,0 +1,23 @@ +// Stub for a main function which reads arguments from the command line, to be +// used by the Eva plug-in. +// This stub emulates non-deterministic input of up to 5 arguments, each up +// to 256 characters long. This is sufficient to ensure arbitrary input in +// virtually every case. +// Do not forget to add option '-main eva_main' in order to use this stub. + +#ifdef __FRAMAC__ +# include "__fc_builtin.h" +int main(int, char **); +static volatile int nondet; +int eva_main() { + int argc = Frama_C_interval(0, 5); + char argv0[256], argv1[256], argv2[256], argv3[256], argv4[256]; + char *argv[6] = {argv0, argv1, argv2, argv3, argv4, 0}; + //@ loop unroll 5; + for (int i = 0; i < 5; i++) { + Frama_C_make_unknown(argv[i], 255); + argv[i][255] = 0; + } + return main(argc, argv); +} +#endif // __FRAMAC__ diff --git a/ioccc/2020/MANIFEST b/ioccc/2020/MANIFEST new file mode 100644 index 0000000000000000000000000000000000000000..3981d86a8f416b0681c86ff3fe56347fdc1cc9c3 --- /dev/null +++ b/ioccc/2020/MANIFEST @@ -0,0 +1,120 @@ +2020/MANIFEST +2020/Makefile +2020/README.text +2020/burton/Makefile +2020/burton/check.sh +2020/burton/check_be.sh +2020/burton/correct +2020/burton/hint.text +2020/burton/prog.c +2020/carlini/Makefile +2020/carlini/hint.text +2020/carlini/prog.c +2020/endoh1/Makefile +2020/endoh1/hilbert16x8.txt +2020/endoh1/hilbert2x2.txt +2020/endoh1/hilbert4x4.txt +2020/endoh1/hilbert8x8.txt +2020/endoh1/hint.text +2020/endoh1/ioccc.txt +2020/endoh1/megumin.txt +2020/endoh1/prog.c +2020/endoh1/prog.orig.c +2020/endoh1/unwinnable.txt +2020/endoh2/Makefile +2020/endoh2/bear.txt +2020/endoh2/hello.txt +2020/endoh2/hint.text +2020/endoh2/prog.c +2020/endoh2/spoiler.zip +2020/endoh2/yoda.txt +2020/endoh3/Makefile +2020/endoh3/hint.text +2020/endoh3/prog.alt.c +2020/endoh3/prog.c +2020/endoh3/run_clock.sh +2020/ferguson1/COMPILING +2020/ferguson1/HACKING +2020/ferguson1/Makefile +2020/ferguson1/bugs.text +2020/ferguson1/cake.jpg +2020/ferguson1/cannibalism.log +2020/ferguson1/chocolate-cake.text +2020/ferguson1/crazy.log +2020/ferguson1/gameplay.text +2020/ferguson1/halfwidth_vs_fullwidth.png +2020/ferguson1/hint.text +2020/ferguson1/ioccc-cake.jpg +2020/ferguson1/play.sh +2020/ferguson1/prog.2.c +2020/ferguson1/prog.3-j.c +2020/ferguson1/prog.3.c +2020/ferguson1/prog.alt.c +2020/ferguson1/prog.c +2020/ferguson1/snake-colours.sh +2020/ferguson1/snake.1 +2020/ferguson1/spoilers.text +2020/ferguson1/termcaps.c +2020/ferguson1/terminals.text +2020/ferguson1/troubleshooting.text +2020/ferguson2/Makefile +2020/ferguson2/cake.jpg +2020/ferguson2/chocolate-cake.text +2020/ferguson2/enigma.1 +2020/ferguson2/hint.text +2020/ferguson2/input.txt +2020/ferguson2/ioccc-cake.jpg +2020/ferguson2/obfuscation.key +2020/ferguson2/obfuscation.text +2020/ferguson2/obfuscation.txt +2020/ferguson2/prog.c +2020/ferguson2/recode.1 +2020/ferguson2/recode.c +2020/ferguson2/recode.text +2020/ferguson2/try.this.txt +2020/giles/Makefile +2020/giles/dtmf.bin +2020/giles/hint.text +2020/giles/pi.wav +2020/giles/prog.c +2020/guidelines.txt +2020/iocccsize-test.sh +2020/iocccsize.c +2020/iocccsize.mk +2020/kurdyukov1/Makefile +2020/kurdyukov1/hint.text +2020/kurdyukov1/prog.c +2020/kurdyukov1/prog.extra.c +2020/kurdyukov1/prog.orig.c +2020/kurdyukov1/prog.x86.asm +2020/kurdyukov1/prog.x86_64.asm +2020/kurdyukov2/Makefile +2020/kurdyukov2/hint.text +2020/kurdyukov2/makegif.sh +2020/kurdyukov2/prog.c +2020/kurdyukov2/prog.png +2020/kurdyukov2/prog.png.c +2020/kurdyukov2/prog.ppm +2020/kurdyukov2/prog.ppm.c +2020/kurdyukov2/sample.jpg +2020/kurdyukov3/Makefile +2020/kurdyukov3/hint.text +2020/kurdyukov3/input.txt +2020/kurdyukov3/prog.c +2020/kurdyukov3/prog.extra.c +2020/kurdyukov3/prog.orig.c +2020/kurdyukov4/Makefile +2020/kurdyukov4/hint.text +2020/kurdyukov4/prog.c +2020/kurdyukov4/rand.c +2020/otterness/Makefile +2020/otterness/hint.text +2020/otterness/prog.c +2020/rules.txt +2020/tsoj/Makefile +2020/tsoj/hint.text +2020/tsoj/prog.c +2020/yang/Makefile +2020/yang/cppp.cc +2020/yang/hint.text +2020/yang/prog.c diff --git a/ioccc/2020/Makefile b/ioccc/2020/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d9f454abb86bef3f2c571516de3387c924323327 --- /dev/null +++ b/ioccc/2020/Makefile @@ -0,0 +1,178 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + + +################ +# tool locations +################ +# +SHELL= /bin/bash +# +BUNZIP2= bunzip2 +BZIP2= bzip2 +CP= cp +CPP= cpp +CURL= curl +DD= dd +ECHO= echo +GREP= grep +GUNZIP= gunzip +GZIP_PROG= gzip +LD= ld +MAKE= make +MKDIR= mkdir +MV= mv +RM= rm +SED= sed +SORT= sort +STRIP= strip +TAR= tar +TR= tr +TRUE= true +UNIQ= uniq + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +CC= cc + + +############### +# IOCCC winners +############### +# +WINNERS= burton carlini endoh1 endoh2 endoh3 ferguson1 ferguson2 giles \ + kurdyukov1 kurdyukov2 kurdyukov3 kurdyukov4 otterness tsoj yang + + +################### +# build all entries +################### +# +all: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) X11_LIBDIR=${X11_LIBDIR} X11_INCDIR=${X11_INCDIR} $@)"; \ + (cd $$i && bear $(MAKE) "X11_LIBDIR=${X11_LIBDIR}" "X11_INCDIR=${X11_INCDIR}" $@); \ + done + +# alternative executable +# +alt: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) X11_LIBDIR=${X11_LIBDIR} X11_INCDIR=${X11_INCDIR} $@)"; \ + (cd $$i && bear $(MAKE) "X11_LIBDIR=${X11_LIBDIR}" "X11_INCDIR=${X11_INCDIR}" $@); \ + done + + +############### +# utility rules +############### +# +everything: all alt + +clean: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && $bear (MAKE) $@); \ + done + +clobber: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done + +nuke: clobber + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done + +install: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done + + +################## +# 133t hacker rulz +################## +# +love: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done + +haste: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done + +waste: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done + +make: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done + +easter_egg: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done + +fabricate fashion form frame manufacture produce: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done + +sandwich: + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done + + +# The IOCCC resident astronomer states +# +charon: supernova + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done + +pluto: supernova + @for i in ${WINNERS} ; do \ + ${ECHO} "(cd $$i && bear $(MAKE) $@)"; \ + (cd $$i && bear $(MAKE) $@); \ + done diff --git a/ioccc/2020/README.text b/ioccc/2020/README.text new file mode 100644 index 0000000000000000000000000000000000000000..e5d85bf7dd8feba68b28bc0a5556517181b5d482 --- /dev/null +++ b/ioccc/2020/README.text @@ -0,0 +1,97 @@ +## 2020 marked the "The Twenty Seventh International Obfuscated C Code Contest" + +Copyright (C) 2020, Landon Curt Noll, Simon Cooper, and Leonid A. +Broukhis. All Rights Reserved. Permission for personal, educational +or non-profit use is granted provided this copyright and notice are +included in its entirety and remains unaltered. All other uses +must receive prior permission from the contest judges. + + +## Standard IOCCC stuff + +The primary IOCCC web site can be found at, + +> <http://www.ioccc.org/> + +Use make to compile entries. It is possible that on non-Un\*x / non-Linux +systems the makefile needs to be changed. See the Makefile for details. + +Look at the source and try to figure out what the programs do, and run +them with various inputs. If you want to, look at the hints files for +spoilers - this year we included most of the information included +by the submitter. + +Read over the makefile for compile/build issues. Your system may require +certain changes (add or remove a library, add or remove a #define). + +Some C compilers are not quite as good as they should be. If yours is +lacking, you may need to compile using clang or gcc instead of your local +compiler. + + +## Remarks on some of the winners + +This year's Best of Show (carlini) is such a novel way of obfuscation that it would be +worth of a special mention in the (future) Best of IOCCC list! + +For some reason, this year's set of winners contains three nostalgic games, +Asteroids (tsoj), Minesweeper (endoh1), and Snake (ferguson1). + +An entry (kurdyukov1) pays homage to a previous winner (2015/hou). + +...We'll stop spouting spoilers now. Have fun exploring all the entries! + + +## Remarks on some of submissions that did not win + +As a rule, we try to compile the entries on a variety of platforms. +Quite a few entries this year could not be built or executed on some of them due to reliance on +library internals or the system runtime. + +A few entries were violating the "2053 significant bytes" rule. If an entry could not be brought to +compliance within a few seconds of looking at the source, it was disqualified. + +One entry tried to get around the size limit by putting the code into +makefile variables and using -D. This is already called out as discouraged +technique in the guidelines, but it is worth a reminder. + +Several promising entries attempted to make use of the `syscall` function using literal syscall numbers. +This is utterly non-portable. + +A note to the authors: when submitting multiple entries, don't let us easily correlate them by +coding style or documentation content, and definitely don't submit nearly identical versions +of your program separately. As we try to judge the entries anonymously, the similarities will cause such +entries to compete against one another, making each less likely to win. + +We hope the authors of non-winning entries will refine their entries and +perhaps re-submit them for the next IOCCC. + +## Final Comments + +One more thing that feels dated is digraphs and trigraphs. + +Please feel free to send us comments and suggestions about the +competition, this README or anything else that you would like to see in +future contests. + +If you use, distribute or publish these entries in some way, please drop +us a line. We enjoy seeing who, where and how the contest is used. + +If you have problems with any of the entries, AND YOU HAVE A FIX, please +send us the fix (patch file or the entire changed file). + +For the latest information on how to contact the IOCCC Judges please visit + +> <http://www.ioccc.org/contact.html> + +For news of the next contest watch: + +> <http://www.ioccc.org/> + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/burton/Makefile b/ioccc/2020/burton/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..397b9923dcd61fdc83299843bc3fc774d6528899 --- /dev/null +++ b/ioccc/2020/burton/Makefile @@ -0,0 +1,617 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +CSTD= -std=c11 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +#CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o prog_be.o +DATA= correct +TARGET= prog prog_be check check_be +# +ALT_OBJ= prog.orig.o +ALT_TARGET= prog.orig prog_be.orig +# +B=6945503773712347754LL +I=5859838231191962459LL +T=0 +S=7 +# +_B=7091606191627001958LL +_I=6006468689561538903LL +_T=1 +_S=0 + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} -DB=${B} -DI=${I} -DT=${T} -DS=${S} $< -o $@ ${LIBS} + +prog_be: prog.c + ${CC} ${CFLAGS} -DB=${_B} -DI=${_I} -DT=${_T} -DS=${_S} $< -o $@ ${LIBS} + +check: check.sh + @${RM} -f $@ + ${CP} -f $< $@ + ${CHMOD} +x $@ + +check_be: check_be.sh + @${RM} -f $@ + ${CP} -f $< $@ + ${CHMOD} +x $@ + +test: check check_be prog prog_be correct + ./check ./prog | ${DIFF} -bw - correct + ./check_be ./prog_be | ${DIFF} -bw - correct + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +prog.orig: prog.orig.c + ${CC} ${CFLAGS} -DB=${B} -DI=${I} -DT=${T} -DS=${S} $< -o $@ ${LIBS} + +prog_be.orig: prog.orig.c + ${CC} ${CFLAGS} -DB=${_B} -DI=${_I} -DT=${_T} -DS=${_S} $< -o $@ ${LIBS} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/burton/check.sh b/ioccc/2020/burton/check.sh new file mode 100644 index 0000000000000000000000000000000000000000..b5cd3ba8587b07dd019b655e69e5f5a68448d7c2 --- /dev/null +++ b/ioccc/2020/burton/check.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +prog="$1" +: ${prog:=./prog} + +check_prog() { + /bin/echo -n "$1 "; $prog $1 +} + +seq 0 255 | while read a; do + check_prog "$a" +done | pr -t -w120 -8 diff --git a/ioccc/2020/burton/check_be.sh b/ioccc/2020/burton/check_be.sh new file mode 100644 index 0000000000000000000000000000000000000000..55a3a2a0ee7a3114e15f30f0401d76ad94f58b53 --- /dev/null +++ b/ioccc/2020/burton/check_be.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +prog="$1" +: ${prog:=prog_be} + +check_code() { + /bin/echo -n "$1 "; $prog $1 | rev +} + +seq 0 255 | while read a; do + check_code "$a" +done | pr -t -w120 -8 diff --git a/ioccc/2020/burton/compile_commands.json b/ioccc/2020/burton/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..722bb5670fc27bd53ac9eb16f1744fad2a207a2e --- /dev/null +++ b/ioccc/2020/burton/compile_commands.json @@ -0,0 +1,26 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-include", + "stdlib.h", + "-include", + "stdio.h", + "-O3", + "-DB=6945503773712347754LL", + "-DI=5859838231191962459LL", + "-DT=0", + "-DS=7", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] diff --git a/ioccc/2020/burton/correct b/ioccc/2020/burton/correct new file mode 100644 index 0000000000000000000000000000000000000000..957e4dd2d49d226b1f8cf6b379ef6c8cdc008dbe --- /dev/null +++ b/ioccc/2020/burton/correct @@ -0,0 +1,32 @@ +0 00000000 32 00100000 64 01000000 96 01100000 128 10000000 160 10100000 192 11000000 224 11100000 +1 00000001 33 00100001 65 01000001 97 01100001 129 10000001 161 10100001 193 11000001 225 11100001 +2 00000010 34 00100010 66 01000010 98 01100010 130 10000010 162 10100010 194 11000010 226 11100010 +3 00000011 35 00100011 67 01000011 99 01100011 131 10000011 163 10100011 195 11000011 227 11100011 +4 00000100 36 00100100 68 01000100 100 01100100 132 10000100 164 10100100 196 11000100 228 11100100 +5 00000101 37 00100101 69 01000101 101 01100101 133 10000101 165 10100101 197 11000101 229 11100101 +6 00000110 38 00100110 70 01000110 102 01100110 134 10000110 166 10100110 198 11000110 230 11100110 +7 00000111 39 00100111 71 01000111 103 01100111 135 10000111 167 10100111 199 11000111 231 11100111 +8 00001000 40 00101000 72 01001000 104 01101000 136 10001000 168 10101000 200 11001000 232 11101000 +9 00001001 41 00101001 73 01001001 105 01101001 137 10001001 169 10101001 201 11001001 233 11101001 +10 00001010 42 00101010 74 01001010 106 01101010 138 10001010 170 10101010 202 11001010 234 11101010 +11 00001011 43 00101011 75 01001011 107 01101011 139 10001011 171 10101011 203 11001011 235 11101011 +12 00001100 44 00101100 76 01001100 108 01101100 140 10001100 172 10101100 204 11001100 236 11101100 +13 00001101 45 00101101 77 01001101 109 01101101 141 10001101 173 10101101 205 11001101 237 11101101 +14 00001110 46 00101110 78 01001110 110 01101110 142 10001110 174 10101110 206 11001110 238 11101110 +15 00001111 47 00101111 79 01001111 111 01101111 143 10001111 175 10101111 207 11001111 239 11101111 +16 00010000 48 00110000 80 01010000 112 01110000 144 10010000 176 10110000 208 11010000 240 11110000 +17 00010001 49 00110001 81 01010001 113 01110001 145 10010001 177 10110001 209 11010001 241 11110001 +18 00010010 50 00110010 82 01010010 114 01110010 146 10010010 178 10110010 210 11010010 242 11110010 +19 00010011 51 00110011 83 01010011 115 01110011 147 10010011 179 10110011 211 11010011 243 11110011 +20 00010100 52 00110100 84 01010100 116 01110100 148 10010100 180 10110100 212 11010100 244 11110100 +21 00010101 53 00110101 85 01010101 117 01110101 149 10010101 181 10110101 213 11010101 245 11110101 +22 00010110 54 00110110 86 01010110 118 01110110 150 10010110 182 10110110 214 11010110 246 11110110 +23 00010111 55 00110111 87 01010111 119 01110111 151 10010111 183 10110111 215 11010111 247 11110111 +24 00011000 56 00111000 88 01011000 120 01111000 152 10011000 184 10111000 216 11011000 248 11111000 +25 00011001 57 00111001 89 01011001 121 01111001 153 10011001 185 10111001 217 11011001 249 11111001 +26 00011010 58 00111010 90 01011010 122 01111010 154 10011010 186 10111010 218 11011010 250 11111010 +27 00011011 59 00111011 91 01011011 123 01111011 155 10011011 187 10111011 219 11011011 251 11111011 +28 00011100 60 00111100 92 01011100 124 01111100 156 10011100 188 10111100 220 11011100 252 11111100 +29 00011101 61 00111101 93 01011101 125 01111101 157 10011101 189 10111101 221 11011101 253 11111101 +30 00011110 62 00111110 94 01011110 126 01111110 158 10011110 190 10111110 222 11011110 254 11111110 +31 00011111 63 00111111 95 01011111 127 01111111 159 10011111 191 10111111 223 11011111 255 11111111 diff --git a/ioccc/2020/burton/hint.text b/ioccc/2020/burton/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..128aace9e2dcf7e3f485c8d7eb9d6f0b18e128a7 --- /dev/null +++ b/ioccc/2020/burton/hint.text @@ -0,0 +1,85 @@ +# Best one-liner + +Dave Burton +<http://snox.net/ioccc> +Twitter: @lv2jmp + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog + + +### Try: + + ./prog 128 + + ./prog_be 128 + + ./prog 170 + + ./prog 85 + +### Selected Judges Remarks: + +This tiny one-liner is a bit-twiddlers delight! It does all of the work +without looping. + +To understand how it works, a good place to start is to look at the hex +value that results when the two magic constants are XOR'ed. + +Once you've figured out what happens with one set of constants, how can +choosing new constants, but using the same computation generate a reversed +result? + +## Author's comments: +Invoke this with a single non-negative integer less than 256, and a useful transformation occurs. + +### Rule 2-ish + +Exporting the constants B,I,T,S to the makefile allows the code +to be compiled for either LE (little-endian) or BE (big-endian) machines(!!), +so they are truly configuration parameters, not logic. + +### Notes + +One <strike>ping</strike> argument only. It will SEGV on zero arguments, and +display strange results if more than one argument. + +Small, non-negative integers only. Useful range is 0 .. 511, sorta, for LE; 0 .. 255 for BE. +Bonus points if you can explain why the limits work this way. + +ASCII character set, 64-bit long longs are required. + +v,a,r,i,a,b,l,e,s_NAME the operation. + +No loops, no branches?!? + +### Compilation + +Compiles cleanly under `clang -Wall -Weverything -pedantic`, +but you need to add `--include stdio.h --include stdlib.h` for the `printf`(3) and `atoi`(3). + +On a little-endian machine: + + clang -include stdio.h -include stdlib.h -Wall -Weverything -pedantic -DB=6945503773712347754LL -DI=5859838231191962459LL -DT=0 -DS=7 -o prog prog.c + +On a big-endian machine: + + clang -include stdio.h -include stdlib.h -Wall -Weverything -pedantic -DB=7091606191627001958LL -DI=6006468689561538903LL -DT=1 -DS=0 -o prog.be prog.c + +You might be interested to compile it both ways on the same host, and try: + + ./prog 1; ./prog.be 1 + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/burton/prog.c b/ioccc/2020/burton/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..60be692611634ba96f4d3a67e415e3382cc1bcd4 --- /dev/null +++ b/ioccc/2020/burton/prog.c @@ -0,0 +1 @@ +int main(int b,char**i){long long n=B,a=I^n,r=(a/b&a)>>4,y=atoi(*++i),_=(((a^n/b)*(y>>T)|y>>S)&r)|(a^r);printf("%.8s\n",(char*)&_);} diff --git a/ioccc/2020/carlini/Makefile b/ioccc/2020/carlini/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..bc40ba6b03a73948a4f27bda89eaa06402717d8e --- /dev/null +++ b/ioccc/2020/carlini/Makefile @@ -0,0 +1,588 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-overlength-strings -Wno-missing-variable-declarations -Wno-format-nonliteral \ + -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-overlength-strings -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-overlength-strings -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +CSTD= -std=c11 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o +DATA= +TARGET= prog +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/carlini/hint.text b/ioccc/2020/carlini/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..36e519ea7858dd851d69bf16b3ed494be609b13d --- /dev/null +++ b/ioccc/2020/carlini/hint.text @@ -0,0 +1,273 @@ +# Best of show - abuse of libc + +Nicholas Carlini <nicholas@carlini.com> +<https://nicholas.carlini.com> + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog + + +### Try: + + # Play with a friend, P1 and P2, squares are numbered 1..9 + ./prog + + +### Selected Judges Remarks: + +This program consists of a single print statement wrapped in a while loop. You +would not think that this would amount to much, but you would be very, very +wrong. A clue to what is happening and how this works is encoded in the +ASCII art of the program source. + + +## Author's comments: +HOW ABOUT A NICE GAME OF <strike>CHESS</strike>TIC-TAC-TOE? + +### USAGE + + cc -o prog prog.c + ./prog + +Alternates between P1 and P2. Enter a digit [1-9] to move: + + 1 | 2 | 3 + --------- + 4 | 5 | 6 + --------- + 7 | 8 | 9 + +The game ends if: + + * A player completes three in a row; that player wins + * All squares are taken; neither player wins + * A player makes an illegal move; their opponent wins + + +### LIMITATIONS + +Bad things may happen if the entered move is outside of the range [1..9] + +While the game will stop if one player tries to overwrite another player's move, +it will happily allow a player to move on top of themself. However, given that +this is an effective no-op and guarantees a loss to a competent opponent, if you +do this you probably deserve to lose. + +Your terminal may beep at you every turn. We'll call this a feature that ... +the program ... is hard at work processing your move! That is! Please be +patient. + +After macro expansion the format string is roughly 100K. This makes some +compilers unhappy, and others slow. (For example, passing GCC the flags -Wall +-Wextra -pedantic will result in a warning about oversized strings.) + +Under some terminals the program may exit early. The following should always work: + + echo "1 2 3 4 5 6 7" | ./prog + + +### OBFUSCATION + +The entirety of the program consists of a single iterated call to printf. + + int main() { + while(*d) printf(fmt, arg); + } + +Here, `fmt` is a single string, and `arg` is a series of arguments to printf. + +While its primary purpose is to serve as The One True Debugger, printf also happens +to be Turing complete. (See "Control-Flow Bending: On the Effectiveness of Control-Flow +Integrity" where we introduced this in an actual, published, academic paper. The +things you can get away with sometimes.) + +We <strike>ab</strike>use this fact to implement the logic of tic-tac-toe entirely within +this one printf call (and a call to scanf() to read user input). + +Here's (briefly) how it works. + +#### Preliminaries + +This program uses three printf format specifiers. +- `%d` takes an integer argument and prints it +- `%s` takes a string argument and prints it +- `%n` takes a pointer and writes (!!) the number of bytes printed so far. + +Okay, everyone probably knows this. Let's get a bit more advanced. + +Format specifiers can take extra "arguments". +- `"%hhn"`: store the number of bytes written mod 256 to the char pointer +- `"%2$d"`: print argument 2 to printf (and not the sequentially next argument) +- `"%8d"`: pad the printed integer to 8 characters +- `"%3$.*4$d"`: print argument 3 to printf with as many zeros as in argument 4. + +For example, the following expression + + printf("%1$.*2$d%3$hhn", 5, 10, &x) + +will have the same effect as if we had written + + x = 10; + +because it will print out `0000000005` (5 padded to size 10) and then write the +number of bytes written to x. + +#### Printf Oriented Programming + +Alright, now we can get to the real fun. + +We perform arbitrary computation with printf treating memory as a binary +array---one bit per pair of bytes: +- The zero bit is represented by the sequence `00 00` +- The one-bit is represented by the sequence `xx 00` where `xx` is any non-zero byte. + +We can use format strings to compute the OR/NOT of arbitrary "bits". + +We'll start with the simplest, OR: + + printf("%1$s%2$s%3$hhn", a, b, c) + +will compute + + *c = strlen(a) + strlen(b) + +but given that `strlen(x)` is `1` for a 1-bit and `0` for a 0-bit, we have + + *c = a | b + +Computing the NOT of a single value is also easy: + + printf("%1$255d%1$s%hhn", a, b) + +will compute + + *b = (strlen(a)+255)%256 = strlen(a)-1 + +and again, because `strlen(x)` is either `1` or `0` we have + + *c = !b + +From here we can compute any binary circuit. Doing something efficient, +though, still takes work. + +#### Tic-Tac-Toe + +The game itself is represented as a board of 18 bits, 9 bits per player, along +with a turn counter that alternates between player 1 and player 2. + +To detect who has won, we implement the following logic. Let A, B, and C be +pointers to three squares in a row to test, and D be where to save if there is a +win or not. + + "%A$s%B$s%C$s%1$253d%11$hhn" // r11 = !(*A & *B & *C) + ZERO + "%11$s%1$255d%11hhn" // r11 = !r11 + ZERO + "%11$s%D$s%D$hhn" // *D = *D | r11 + +That is, we set `*D` to `1` if there is a three-in-a-row. We repeat this for all +possible three-in-a-row configurations, for both players. + +The ZERO macro ensures that the number of bytes written out is 0 mod 256 with +the following expression + + "%1$hhn%1$s" (repeated 256 times) + +where argument 1 is a pointer to a temporary variable followed by a null byte. + +This works because if the current count is 0 mod 256, then "%1$hhn" will write +zero to argument 1 and then "%1$s" will never emit any text. If, on the other +hand, the count is not 0 mod 256, a length-1 string will be written to argument +1, and then "%1$s" will increment the count by one. By repeating this 256 +times we're eventually going to reach 0 mod 256. + +Checking if there has been an invalid move is achieved similarly. + +In order to decide what to print out, we have to cast the "in-memory" array of +bits to Xs and Os to print out. This is actually rather straightforward. Given +in 1$ the pointer to player 1's square, and 2$ the pointer to player 2's, and +in 3$ the pointer to the board string, we can compute + + "%1$s" (repeated 47 times) "%2$s" (repeated 56 times) %1$32d%3$hhn" + +which will, in effect, compute + + *r3 = (*r1) * 47 + (*r2) * 56 + 32 + +which will output ' ' if neither are true, 'X' if r1 is, or 'O' if r2 is. + + +#### Further Obfuscations + +In order to be able to finally display the board, while still only using one +printf statement, we finish the statement with + + "\n\033[2J\n%26$s" + +which is the escape sequence to clear the screen, and then prints argument 26. +Argument 26 is a pointer to a char* in memory, that initially is undefined, +but within the printf statement we will construct this string to look like a +tic-tac-toe board. + +After the board, we need to print one of the following strings: + + P1>_ + P2>_ + P1 WINS + P2 WINS + P1 TIES + P2 TIES + +Depending on if it's P1 or P2's turn to move, the game is over and someone +won, or the game is over and it is a draw. + +This turns out not to be as hard as it might look. Using the same trick as +before, we set byte four to be + + *byte4 = is_win * 'W' + is_tie * 'T' + +The byte `'I'` and `'S'` can always be the same, and we do the same for `'E'`/`'N'`. + +We do this same on-the-fly creation of the `scanf()` format string, but for a +different reason. We first want to run `printf()` to show the first board, and +then alternate between runs to `scanf()` and `printf()` reading and then +displaying moves. importantly, we *do not* want a final scanf when the game +ends. It should just exit. + +One option would be to implement the logic as + + printf() + while (*ok) { + scanf(); + printf(); + } + +but this would DOUBLE the number of calls to printf we require. So instead we +implement it like this + + while (*ok) { + scanf(); + printf(); + } + +(In reality we actually pass `scanf()` as an argument to avoid the extra +statement, but it has the same effect.) + +Notice there is now no initial `printf()`. In order make sure the program doesn't +block before the first `printf()`, but we initialize the `scanf()` format to the null +string so that it returns right away without blocking. The first time the `printf()` +call runs, it writes out "%hhd" to create the `scanf()` format string. + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/carlini/prog.c b/ioccc/2020/carlini/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..97df3f83685312382dcbd66a938bb3c003d7666f --- /dev/null +++ b/ioccc/2020/carlini/prog.c @@ -0,0 +1,52 @@ +#include <stdio.h> + +#define N(a) "%"#a"$hhn" +#define O(a,b) "%10$"#a"d"N(b) +#define U "%10$.*37$d" +#define G(a) "%"#a"$s" +#define H(a,b) G(a)G(b) +#define T(a) a a +#define s(a) T(a)T(a) +#define A(a) s(a)T(a)a +#define n(a) A(a)a +#define D(a) n(a)A(a) +#define C(a) D(a)a +#define R C(C(N(12)G(12))) +#define o(a,b,c) C(H(a,a))D(G(a))C(H(b,b)G(b))n(G(b))O(32,c)R +#define SS O(78,55)R "\n\033[2J\n%26$s"; +#define E(a,b,c,d) H(a,b)G(c)O(253,11)R G(11)O(255,11)R H(11,d)N(d)O(253,35)R +#define S(a,b) O(254,11)H(a,b)N(68)R G(68)O(255,68)N(12)H(12,68)G(67)N(67) + +char* fmt = O(10,39)N(40)N(41)N(42)N(43)N(66)N(69)N(24)O(22,65)O(5,70)O(8,44)N( + 45)N(46)N (47)N(48)N( 49)N( 50)N( 51)N(52)N(53 )O( 28, + 54)O(5, 55) O(2, 56)O(3,57)O( 4,58 )O(13, 73)O(4, + 71 )N( 72)O (20,59 )N(60)N(61)N( 62)N (63)N (64)R R + E(1,2, 3,13 )E(4, 5,6,13)E(7,8,9 ,13)E(1,4 ,7,13)E + (2,5,8, 13)E( 3,6,9,13)E(1,5, 9,13)E(3 ,5,7,13 + )E(14,15, 16,23) E(17,18,19,23)E( 20, 21, 22,23)E + (14,17,20,23)E(15, 18,21,23)E(16,19, 22 ,23)E( 14, 18, + 22,23)E(16,18,20, 23)R U O(255 ,38)R G ( 38)O( 255,36) + R H(13,23)O(255, 11)R H(11,36) O(254 ,36) R G( 36 ) O( + 255,36)R S(1,14 )S(2,15)S(3, 16)S(4, 17 )S (5, 18)S(6, + 19)S(7,20)S(8, 21)S(9 ,22)H(13,23 )H(36, 67 )N(11)R + G(11)""O(255, 25 )R s(C(G(11) ))n (G( 11) )G( + 11)N(54)R C( "aa") s(A( G(25)))T (G(25))N (69)R o + (14,1,26)o( 15, 2, 27)o (16,3,28 )o( 17,4, 29)o(18 + ,5,30)o(19 ,6,31)o( 20,7,32)o (21,8,33)o (22 ,9, + 34)n(C(U) )N( 68)R H( 36,13)G(23) N(11)R C(D( G(11))) + D(G(11))G(68)N(68)R G(68)O(49,35)R H(13,23)G(67)N(11)R C(H(11,11)G( + 11))A(G(11))C(H(36,36)G(36))s(G(36))O(32,58)R C(D(G(36)))A(G(36))SS + +#define arg d+6,d+8,d+10,d+12,d+14,d+16,d+18,d+20,d+22,0,d+46,d+52,d+48,d+24,d\ + +26,d+28,d+30,d+32,d+34,d+36,d+38,d+40,d+50,(scanf(d+126,d+4),d+(6\ + -2)+18*(1-d[2]%2)+d[4]*2),d,d+66,d+68,d+70, d+78,d+80,d+82,d+90,d+\ + 92,d+94,d+97,d+54,d[2],d+2,d+71,d+77,d+83,d+89,d+95,d+72,d+73,d+74\ + ,d+75,d+76,d+84,d+85,d+86,d+87,d+88,d+100,d+101,d+96,d+102,d+99,d+\ + 67,d+69,d+79,d+81,d+91,d+93,d+98,d+103,d+58,d+60,d+98,d+126,d+127,\ + d+128,d+129 + +char d[538] = {1,0,10,0,10}; + +int main() { + while(*d) printf(fmt, arg); +} diff --git a/ioccc/2020/endoh1/Makefile b/ioccc/2020/endoh1/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7efa6d2d30c08710ed55124a8cb71226309ab749 --- /dev/null +++ b/ioccc/2020/endoh1/Makefile @@ -0,0 +1,589 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-missing-variable-declarations -Wno-shorten-64-to-32 -Wno-comma -Wno-shadow \ + -Wno-missing-prototypes -Wno-sign-conversion -Wno-implicit-int-conversion \ + -Wno-conversion -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-misleading-indentation -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +CSILENCE= -Wno-misleading-indentation -Wno-unknown-warning-option +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +CSTD= -std=c11 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +#LIBS= +#LIBS= -L ${X11_LIBDIR} +LIBS= -lcurses + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o +DATA= ioccc.txt unwinnable.txt +TARGET= prog +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/endoh1/hilbert16x8.txt b/ioccc/2020/endoh1/hilbert16x8.txt new file mode 100644 index 0000000000000000000000000000000000000000..bd37fbf0a651592778677ef4ea7eae93ed2af8e0 --- /dev/null +++ b/ioccc/2020/endoh1/hilbert16x8.txt @@ -0,0 +1,33 @@ +64 32 510 +510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 +574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 +638 639 0 640 641 642 1 2 3 4 5 6 7 8 9 643 644 645 10 11 12 13 14 15 16 17 18 646 647 648 19 20 21 22 23 24 25 26 27 649 650 651 28 29 30 31 32 33 34 35 36 652 653 654 37 38 39 40 41 42 43 44 45 655 +656 657 46 658 659 660 47 661 662 663 664 665 666 667 48 668 669 670 49 671 672 673 674 675 676 677 50 678 679 680 51 681 682 683 684 685 686 687 52 688 689 690 53 691 692 693 694 695 696 697 54 698 699 700 55 701 702 703 704 705 706 707 56 708 +709 710 57 711 712 713 58 714 715 716 717 718 719 720 59 721 722 723 60 724 725 726 727 728 729 730 61 731 732 733 62 734 735 736 737 738 739 740 63 741 742 743 64 744 745 746 747 748 749 750 65 751 752 753 66 754 755 756 757 758 759 760 67 761 +762 763 68 764 765 766 69 767 768 769 770 771 772 773 70 774 775 776 71 777 778 779 780 781 782 783 72 784 785 786 73 787 788 789 790 791 792 793 74 794 795 796 75 797 798 799 800 801 802 803 76 804 805 806 77 807 808 809 810 811 812 813 78 814 +815 816 79 80 81 82 83 817 818 819 84 85 86 87 88 820 821 822 89 90 91 92 93 823 824 825 94 95 96 97 98 826 827 828 99 100 101 102 103 829 830 831 104 105 106 107 108 832 833 834 109 110 111 112 113 835 836 837 114 115 116 117 118 838 +839 840 841 842 843 844 845 846 847 848 119 849 850 851 852 853 854 855 856 857 858 859 120 860 861 862 863 864 865 866 867 868 869 870 121 871 872 873 874 875 876 877 878 879 880 881 122 882 883 884 885 886 887 888 889 890 891 892 123 893 894 895 896 897 +898 899 900 901 902 903 904 905 906 907 124 908 909 910 911 912 913 914 915 916 917 918 125 919 920 921 922 923 924 925 926 927 928 929 126 930 931 932 933 934 935 936 937 938 939 940 127 941 942 943 944 945 946 947 948 949 950 951 128 952 953 954 955 956 +957 958 959 960 961 962 963 964 965 966 129 967 968 969 970 971 972 973 974 975 976 977 130 978 979 980 981 982 983 984 985 986 987 988 131 989 990 991 992 993 994 995 996 997 998 999 132 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 133 1011 1012 1013 1014 1015 +1016 1017 134 135 136 137 138 1018 1019 1020 139 140 141 142 143 1021 1022 1023 144 145 146 147 148 1024 1025 1026 149 150 151 152 153 1027 1028 1029 154 1030 1031 1032 155 156 157 158 159 1033 1034 1035 160 1036 1037 1038 161 162 163 164 165 1039 1040 1041 166 167 168 169 170 1042 +1043 1044 171 1045 1046 1047 172 1048 1049 1050 1051 1052 1053 1054 173 1055 1056 1057 174 1058 1059 1060 1061 1062 1063 1064 175 1065 1066 1067 176 1068 1069 1070 177 1071 1072 1073 178 1074 1075 1076 179 1077 1078 1079 180 1080 1081 1082 181 1083 1084 1085 182 1086 1087 1088 1089 1090 1091 1092 183 1093 +1094 1095 184 1096 1097 1098 185 1099 1100 1101 1102 1103 1104 1105 186 1106 1107 1108 187 1109 1110 1111 1112 1113 1114 1115 188 1116 1117 1118 189 1119 1120 1121 190 1122 1123 1124 191 1125 1126 1127 192 1128 1129 1130 193 1131 1132 1133 194 1134 1135 1136 195 1137 1138 1139 1140 1141 1142 1143 196 1144 +1145 1146 197 1147 1148 1149 198 1150 1151 1152 1153 1154 1155 1156 199 1157 1158 1159 200 1160 1161 1162 1163 1164 1165 1166 201 1167 1168 1169 202 1170 1171 1172 203 1173 1174 1175 204 1176 1177 1178 205 1179 1180 1181 206 1182 1183 1184 207 1185 1186 1187 208 1188 1189 1190 1191 1192 1193 1194 209 1195 +1196 1197 210 1198 1199 1200 211 212 213 214 215 216 217 218 219 1201 1202 1203 220 221 222 223 224 225 226 227 228 1204 1205 1206 229 1207 1208 1209 230 231 232 233 234 1210 1211 1212 235 236 237 238 239 1213 1214 1215 240 1216 1217 1218 241 242 243 244 245 246 247 248 249 1219 +1220 1221 250 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 251 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 252 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 +1281 1282 253 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 254 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 255 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 +1342 1343 256 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 257 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 258 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 +1403 1404 259 260 261 262 263 1405 1406 1407 264 265 266 267 268 269 270 271 272 273 274 275 276 1408 1409 1410 277 278 279 280 281 1411 1412 1413 282 283 284 285 286 1414 1415 1416 287 288 289 290 291 1417 1418 1419 292 1420 1421 1422 293 294 295 296 297 298 299 300 301 1423 +1424 1425 1426 1427 1428 1429 302 1430 1431 1432 303 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 304 1444 1445 1446 305 1447 1448 1449 1450 1451 1452 1453 306 1454 1455 1456 307 1457 1458 1459 308 1460 1461 1462 309 1463 1464 1465 310 1466 1467 1468 311 1469 1470 1471 1472 1473 1474 1475 312 1476 +1477 1478 1479 1480 1481 1482 313 1483 1484 1485 314 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 315 1497 1498 1499 316 1500 1501 1502 1503 1504 1505 1506 317 1507 1508 1509 318 1510 1511 1512 319 1513 1514 1515 320 1516 1517 1518 321 1519 1520 1521 322 1522 1523 1524 1525 1526 1527 1528 323 1529 +1530 1531 1532 1533 1534 1535 324 1536 1537 1538 325 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 326 1550 1551 1552 327 1553 1554 1555 1556 1557 1558 1559 328 1560 1561 1562 329 1563 1564 1565 330 1566 1567 1568 331 1569 1570 1571 332 1572 1573 1574 333 1575 1576 1577 1578 1579 1580 1581 334 1582 +1583 1584 335 336 337 338 339 1585 1586 1587 340 341 342 343 344 1588 1589 1590 345 346 347 348 349 1591 1592 1593 350 351 352 353 354 1594 1595 1596 355 1597 1598 1599 356 357 358 359 360 1600 1601 1602 361 1603 1604 1605 362 363 364 365 366 1606 1607 1608 367 368 369 370 371 1609 +1610 1611 372 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 373 1623 1624 1625 374 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 375 1637 1638 1639 376 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 377 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 378 1662 1663 1664 1665 1666 +1667 1668 379 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 380 1680 1681 1682 381 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 382 1694 1695 1696 383 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 384 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 385 1719 1720 1721 1722 1723 +1724 1725 386 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 387 1737 1738 1739 388 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 389 1751 1752 1753 390 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 391 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 392 1776 1777 1778 1779 1780 +1781 1782 393 1783 1784 1785 394 395 396 397 398 1786 1787 1788 399 1789 1790 1791 400 1792 1793 1794 401 402 403 404 405 1795 1796 1797 406 1798 1799 1800 407 408 409 410 411 1801 1802 1803 412 413 414 415 416 1804 1805 1806 417 418 419 420 421 1807 1808 1809 422 423 424 425 426 1810 +1811 1812 427 1813 1814 1815 428 1816 1817 1818 429 1819 1820 1821 430 1822 1823 1824 431 1825 1826 1827 432 1828 1829 1830 433 1831 1832 1833 434 1834 1835 1836 1837 1838 1839 1840 435 1841 1842 1843 436 1844 1845 1846 1847 1848 1849 1850 437 1851 1852 1853 438 1854 1855 1856 1857 1858 1859 1860 439 1861 +1862 1863 440 1864 1865 1866 441 1867 1868 1869 442 1870 1871 1872 443 1873 1874 1875 444 1876 1877 1878 445 1879 1880 1881 446 1882 1883 1884 447 1885 1886 1887 1888 1889 1890 1891 448 1892 1893 1894 449 1895 1896 1897 1898 1899 1900 1901 450 1902 1903 1904 451 1905 1906 1907 1908 1909 1910 1911 452 1912 +1913 1914 453 1915 1916 1917 454 1918 1919 1920 455 1921 1922 1923 456 1924 1925 1926 457 1927 1928 1929 458 1930 1931 1932 459 1933 1934 1935 460 1936 1937 1938 1939 1940 1941 1942 461 1943 1944 1945 462 1946 1947 1948 1949 1950 1951 1952 463 1953 1954 1955 464 1956 1957 1958 1959 1960 1961 1962 465 1963 +1964 1965 466 467 468 469 470 1966 1967 1968 471 472 473 474 475 1969 1970 1971 476 477 478 479 480 1972 1973 1974 481 482 483 484 485 1975 1976 1977 486 487 488 489 490 1978 1979 1980 491 492 493 494 495 496 497 498 499 1981 1982 1983 500 501 502 503 504 505 506 507 508 1984 +1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 509 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 diff --git a/ioccc/2020/endoh1/hilbert2x2.txt b/ioccc/2020/endoh1/hilbert2x2.txt new file mode 100644 index 0000000000000000000000000000000000000000..0e501c482f2035d299cdebce9a71bb0bb3a5f207 --- /dev/null +++ b/ioccc/2020/endoh1/hilbert2x2.txt @@ -0,0 +1,9 @@ +8 8 13 +13 14 15 16 17 18 19 20 +21 22 23 24 25 26 27 28 +29 30 0 31 32 33 1 34 +35 36 2 37 38 39 3 40 +41 42 4 43 44 45 5 46 +47 48 6 49 50 51 7 52 +53 54 8 9 10 11 12 55 +56 57 58 59 60 61 62 63 diff --git a/ioccc/2020/endoh1/hilbert4x4.txt b/ioccc/2020/endoh1/hilbert4x4.txt new file mode 100644 index 0000000000000000000000000000000000000000..f9e2541a482a816cf227ac0ba595a1a598c001cd --- /dev/null +++ b/ioccc/2020/endoh1/hilbert4x4.txt @@ -0,0 +1,17 @@ +16 16 61 +61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 +77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 +93 94 0 95 96 97 1 2 3 4 5 6 7 8 9 98 +99 100 10 101 102 103 11 104 105 106 107 108 109 110 12 111 +112 113 13 114 115 116 14 117 118 119 120 121 122 123 15 124 +125 126 16 127 128 129 17 130 131 132 133 134 135 136 18 137 +138 139 19 20 21 22 23 140 141 142 24 25 26 27 28 143 +144 145 146 147 148 149 150 151 152 153 29 154 155 156 157 158 +159 160 161 162 163 164 165 166 167 168 30 169 170 171 172 173 +174 175 176 177 178 179 180 181 182 183 31 184 185 186 187 188 +189 190 32 33 34 35 36 191 192 193 37 38 39 40 41 194 +195 196 42 197 198 199 43 200 201 202 203 204 205 206 44 207 +208 209 45 210 211 212 46 213 214 215 216 217 218 219 47 220 +221 222 48 223 224 225 49 226 227 228 229 230 231 232 50 233 +234 235 51 236 237 238 52 53 54 55 56 57 58 59 60 239 +240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 diff --git a/ioccc/2020/endoh1/hilbert8x8.txt b/ioccc/2020/endoh1/hilbert8x8.txt new file mode 100644 index 0000000000000000000000000000000000000000..051b323ead46a954f6a47f4e37097008b3cb4025 --- /dev/null +++ b/ioccc/2020/endoh1/hilbert8x8.txt @@ -0,0 +1,33 @@ +32 32 253 +253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 +285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 +317 318 0 319 320 321 1 2 3 4 5 6 7 8 9 322 323 324 10 11 12 13 14 15 16 17 18 325 326 327 19 328 +329 330 20 331 332 333 21 334 335 336 337 338 339 340 22 341 342 343 23 344 345 346 347 348 349 350 24 351 352 353 25 354 +355 356 26 357 358 359 27 360 361 362 363 364 365 366 28 367 368 369 29 370 371 372 373 374 375 376 30 377 378 379 31 380 +381 382 32 383 384 385 33 386 387 388 389 390 391 392 34 393 394 395 35 396 397 398 399 400 401 402 36 403 404 405 37 406 +407 408 38 39 40 41 42 409 410 411 43 44 45 46 47 412 413 414 48 49 50 51 52 415 416 417 53 54 55 56 57 418 +419 420 421 422 423 424 425 426 427 428 58 429 430 431 432 433 434 435 436 437 438 439 59 440 441 442 443 444 445 446 447 448 +449 450 451 452 453 454 455 456 457 458 60 459 460 461 462 463 464 465 466 467 468 469 61 470 471 472 473 474 475 476 477 478 +479 480 481 482 483 484 485 486 487 488 62 489 490 491 492 493 494 495 496 497 498 499 63 500 501 502 503 504 505 506 507 508 +509 510 64 65 66 67 68 511 512 513 69 70 71 72 73 514 515 516 74 75 76 77 78 517 518 519 79 80 81 82 83 520 +521 522 84 523 524 525 85 526 527 528 529 530 531 532 86 533 534 535 87 536 537 538 539 540 541 542 88 543 544 545 89 546 +547 548 90 549 550 551 91 552 553 554 555 556 557 558 92 559 560 561 93 562 563 564 565 566 567 568 94 569 570 571 95 572 +573 574 96 575 576 577 97 578 579 580 581 582 583 584 98 585 586 587 99 588 589 590 591 592 593 594 100 595 596 597 101 598 +599 600 102 601 602 603 103 104 105 106 107 108 109 110 111 604 605 606 112 113 114 115 116 117 118 119 120 607 608 609 121 610 +611 612 122 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 123 640 +641 642 124 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 125 670 +671 672 126 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 127 700 +701 702 128 129 130 131 132 703 704 705 133 134 135 136 137 138 139 140 141 142 143 144 145 706 707 708 146 147 148 149 150 709 +710 711 712 713 714 715 151 716 717 718 152 719 720 721 722 723 724 725 726 727 728 729 153 730 731 732 154 733 734 735 736 737 +738 739 740 741 742 743 155 744 745 746 156 747 748 749 750 751 752 753 754 755 756 757 157 758 759 760 158 761 762 763 764 765 +766 767 768 769 770 771 159 772 773 774 160 775 776 777 778 779 780 781 782 783 784 785 161 786 787 788 162 789 790 791 792 793 +794 795 163 164 165 166 167 796 797 798 168 169 170 171 172 799 800 801 173 174 175 176 177 802 803 804 178 179 180 181 182 805 +806 807 183 808 809 810 811 812 813 814 815 816 817 818 184 819 820 821 185 822 823 824 825 826 827 828 829 830 831 832 186 833 +834 835 187 836 837 838 839 840 841 842 843 844 845 846 188 847 848 849 189 850 851 852 853 854 855 856 857 858 859 860 190 861 +862 863 191 864 865 866 867 868 869 870 871 872 873 874 192 875 876 877 193 878 879 880 881 882 883 884 885 886 887 888 194 889 +890 891 195 892 893 894 196 197 198 199 200 895 896 897 201 898 899 900 202 901 902 903 203 204 205 206 207 904 905 906 208 907 +908 909 209 910 911 912 210 913 914 915 211 916 917 918 212 919 920 921 213 922 923 924 214 925 926 927 215 928 929 930 216 931 +932 933 217 934 935 936 218 937 938 939 219 940 941 942 220 943 944 945 221 946 947 948 222 949 950 951 223 952 953 954 224 955 +956 957 225 958 959 960 226 961 962 963 227 964 965 966 228 967 968 969 229 970 971 972 230 973 974 975 231 976 977 978 232 979 +980 981 233 234 235 236 237 982 983 984 238 239 240 241 242 985 986 987 243 244 245 246 247 988 989 990 248 249 250 251 252 991 +992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 diff --git a/ioccc/2020/endoh1/hint.text b/ioccc/2020/endoh1/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..93415fee817b184e6843d2b62231e05b90861278 --- /dev/null +++ b/ioccc/2020/endoh1/hint.text @@ -0,0 +1,152 @@ +# Most explosive + +Yusuke Endoh +Twitter: @mametter + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog + +### Try: + + # Try resizing the terminal window before the first click. + + # Try resizing the terminal window after the first click. + + ./prog ioccc.txt + + ./prog unwinnable.txt + +### Selected Judges Remarks: + +When playing Minesweeper, a misclick might ruin a game, so why not leave the routine to the computer? +This program automatically uncovers mines according to several rules, and leaves guessing (and applying +the most straightforward of the rules -- just for fun, perhaps?) to the user. + +Try creating your own input files according to the author's remarks. Did you encounter any problems? + +The submission was in violation of the "2053" size rule by one character, likely a late typo. It was easy to fix. + + + +## Author's comments: +### Semi-automatic Minesweeper + +Minesweeper is a game to sweep mines, as you know. The task consists of two parts: + +A) choose a random cell based on your sixth sense +B) identify a non-mine cell based on logical inference + +However, (B) is error-prone, and a waste of time. You must use a computer to do such a boring task! + +This program is a semi-automatic minesweeper which does Part (B) automatically. +All you have to do is (A). You can test if you are lucky or not. + +#### How to use + +It uses ncurses: + + $ gcc -o prog prog.c -lncurses + $ ./prog + +You will see a terminal-wide field of a minesweeper. Probe a cell by mouse click. +If a cell turns out to have a mine (or not), the program determines whether its neighbors have a mine or not, and automatically probes (or flags) the cell. + +* `R`: new game (You can also click the smiley face at the top line.) +* `Q`: quit + +#### Internal + +The program uses four types of local inference: + +#### Rule 1 + +If the number of a cell is equal to the count of the flagged neighbors, all the unprobed neighbors are probed. + +Example: + +``` + ? ? ? . . . + ? 3 ? => . 3 . + ! ! ! ! ! ! +``` + +Note that `?` is a unprobed cell (it is unknown whether the cell has a mine or not); `!` is a flagged cell (it is already known that the cell has a mine); and `.` is a probed cell (it is already known that the cell has no mine). + +#### Rule 2 + +If the number of a cell is equal to the count of the unprobed or flagged neighbors, all the unprobed neighbors are flagged, + +Example: + +``` + . ? ? . ! ! + . 4 ? => . 4 ! + . 2 ! . 2 ! +``` + +#### Rule 3 + +Consider two number cells A and B. If A is equal to the difference of B and the count of B's unprobed and flagged neighbors that are not A's neighbors, all A's unprobed neighbors that are not B's neighbors are probed. + +Example: + +``` + ? ? ? . . . + ? 1 ? ? => . 1 ? ? + ? ? 4 . . ? 4 . + ? . ! ? . ! +``` + +A and B are probed cells whose numbers are, respectively, 1 and 4. The count of B's unprobed and flagged neighbors that are not A's neighbors is three (one `!` and two `?`s). Since A (1) == B (4) - the count (3), the left and top unprobed cells are probed. + +#### Rule 4 + +Consider two number cells A and B. If B is equal to the difference of A and the count of A's unprobed and flagged neighbors that are not B's neighbors, all A's unprobed neighbors that are not B's neighbors are flagged. + +``` + ? ? ? ? ! ? ? ? + ? 3 1 2 => ! 3 1 2 + 2 2 . . 2 2 . . +``` + +A and B are probed cells whose numbers are, respectively, 3 and 1. The count of A's unprobed and flagged neighbors that are not B's neighbors is two (left `?`s). Since B (1) == A (3) - the count (2), the left unprobed cells are flagged. + +#### Note + +Interestingly, these complex rules can be integrated to one simple rule. Analyze the code. + +#### One more thing + +You can also play with a prepared map. + + $ ./prog ioccc.txt + +The format of the text is: + + width height number-of-mines priorities-of-each-cell... + +There are mines in a cell whose "priorities-of-each-cell" is less than "number-of-mines". +(But the mine in the first-clicked cell is removed.) + +#### Bug fixes and Credits + +The judges pointed out a bug of the original version that I submitted (prog.orig.c). Because this program does not provide a feature to flag unprobed cells manually, we can do nothing if the number of unprobed cells are equal to the number of mines remaining; unwinnable.txt is an example for such a case. +Thus, I implemented an additional rule to flag all unprobed cells in such a case into the final version (prog.c). + +Ilya Kurdyukov also pointed out a warning "ignoring return value of 'fscanf'" only when "-O3" is used. So I changed the code a little to pretend to use the return value of fscanf. + +Don Yang (omoikane) contributed another example map "megumin.txt" which is the Explosion Arch-Wizard. + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/endoh1/ioccc.txt b/ioccc/2020/endoh1/ioccc.txt new file mode 100644 index 0000000000000000000000000000000000000000..06effe48ea7269c13346560d5731a67f3576960b --- /dev/null +++ b/ioccc/2020/endoh1/ioccc.txt @@ -0,0 +1 @@ +25 9 44 80 44 101 194 220 134 60 144 183 223 149 81 131 59 55 146 57 113 114 63 75 135 91 52 177 99 100 192 216 126 54 206 51 106 176 128 85 105 208 104 219 98 205 160 211 197 152 93 204 76 127 171 25 147 173 17 29 40 185 153 30 41 20 132 193 31 33 42 161 186 26 27 9 137 138 48 121 11 108 174 5 190 19 214 133 14 201 50 97 142 4 129 136 74 191 21 199 109 164 130 62 94 28 170 64 7 116 38 182 200 37 123 86 92 215 23 224 112 102 165 18 218 73 178 163 120 124 36 222 148 24 217 22 69 89 16 49 119 158 202 2 187 156 196 212 12 111 175 115 107 169 70 0 79 72 3 34 35 103 77 10 6 1 209 122 13 15 32 56 61 43 39 8 53 78 88 117 207 210 150 71 125 139 87 143 155 141 68 90 65 140 47 203 168 67 84 172 96 195 66 110 162 221 181 166 154 180 198 184 45 95 167 46 145 213 159 189 118 82 151 83 179 157 188 58 diff --git a/ioccc/2020/endoh1/megumin.txt b/ioccc/2020/endoh1/megumin.txt new file mode 100644 index 0000000000000000000000000000000000000000..c8e1b307f6fdd5c07f625c53518a432b3d2a1573 --- /dev/null +++ b/ioccc/2020/endoh1/megumin.txt @@ -0,0 +1,36 @@ +64 35 363 +363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 +427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 +491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 0 1 2 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 +552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 3 4 5 587 588 589 6 7 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 +611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 8 9 10 643 644 645 646 647 648 649 650 11 12 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 +670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 13 14 15 699 700 701 702 703 704 705 706 707 708 709 710 711 16 17 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 +729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 18 19 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 20 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 +790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 21 22 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 23 24 836 837 838 839 840 841 842 843 844 845 846 847 848 849 +850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 25 26 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 27 898 899 900 901 902 903 904 905 906 907 908 909 910 +911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 28 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 29 961 962 963 964 965 966 967 968 969 970 971 972 +973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 30 31 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 32 33 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 +1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 34 35 36 37 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 38 1083 1084 1085 1086 1087 1088 1089 1090 1091 +1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 39 1110 1111 40 41 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 42 43 44 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 45 1141 1142 1143 1144 1145 1146 1147 1148 +1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 46 47 48 1166 1167 1168 1169 49 50 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 51 52 53 54 55 1181 1182 1183 1184 1185 56 57 58 59 1186 1187 1188 1189 1190 60 1191 1192 1193 1194 1195 1196 1197 +1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 61 62 1215 1216 1217 63 64 65 66 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 67 68 69 1230 1231 1232 1233 1234 1235 1236 70 1237 1238 71 72 73 74 1239 1240 75 1241 1242 1243 1244 1245 1246 +1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 76 1267 1268 77 78 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 79 1283 1284 1285 80 1286 1287 1288 1289 81 1290 1291 1292 1293 1294 1295 1296 1297 1298 82 1299 1300 1301 1302 1303 +1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 83 1320 1321 84 85 1322 1323 86 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 87 88 1334 1335 1336 1337 1338 1339 89 90 91 1340 1341 1342 92 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 93 94 1353 1354 1355 +1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 95 96 1371 1372 1373 97 98 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 99 100 101 1386 1387 1388 1389 102 103 104 105 1390 1391 1392 1393 106 1394 1395 1396 1397 1398 1399 107 1400 1401 1402 108 1403 1404 1405 +1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 109 110 111 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 112 113 114 115 1437 1438 1439 1440 116 117 118 1441 1442 1443 1444 119 1445 1446 1447 1448 1449 120 1450 1451 1452 1453 1454 121 1455 1456 +1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 122 123 124 125 126 127 1468 128 129 130 1469 1470 131 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 132 133 134 1481 1482 1483 1484 1485 1486 135 1487 1488 1489 1490 1491 136 1492 1493 1494 1495 1496 137 1497 138 1498 139 1499 140 1500 1501 +1502 1503 1504 1505 1506 1507 1508 1509 141 142 143 1510 1511 1512 1513 144 145 1514 146 147 1515 1516 1517 1518 148 149 150 1519 1520 1521 1522 1523 1524 1525 1526 151 1527 1528 1529 152 153 1530 1531 1532 1533 1534 1535 1536 1537 154 1538 1539 1540 1541 1542 155 1543 1544 1545 1546 1547 156 1548 1549 +1550 1551 1552 1553 1554 1555 157 158 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 159 1566 1567 160 1568 161 162 163 164 165 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 166 167 168 169 1579 1580 1581 1582 1583 1584 1585 170 171 1586 1587 1588 1589 1590 172 1591 173 1592 174 175 1593 1594 +1595 1596 1597 176 177 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 178 179 180 181 1612 1613 182 183 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 184 185 186 187 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 188 1639 1640 1641 1642 189 1643 1644 +1645 1646 190 191 192 193 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 194 195 196 197 1660 1661 1662 1663 1664 1665 1666 1667 198 199 200 201 202 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 203 1681 1682 1683 1684 1685 1686 204 1687 1688 205 1689 206 1690 1691 +1692 1693 1694 1695 207 208 209 210 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 211 212 213 1709 1710 1711 214 215 216 1712 1713 217 218 219 220 1714 1715 221 222 1716 1717 1718 1719 1720 1721 1722 1723 223 224 1724 1725 1726 1727 1728 1729 1730 225 1731 1732 1733 226 1734 1735 +1736 1737 1738 1739 1740 1741 227 228 229 230 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 231 232 233 234 1759 1760 235 236 1761 237 238 239 240 1762 1763 1764 1765 1766 241 1767 1768 242 243 244 1769 1770 1771 1772 1773 1774 245 246 1775 1776 247 1777 1778 +1779 1780 1781 1782 1783 1784 1785 1786 248 249 250 251 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 252 253 1804 1805 1806 1807 254 255 256 257 258 259 1808 1809 1810 260 261 262 1811 1812 1813 263 1814 1815 1816 1817 1818 1819 1820 264 265 1821 266 1822 1823 +1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 267 268 269 270 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 271 1850 1851 1852 1853 272 273 274 275 276 277 1854 1855 278 279 280 281 282 1856 1857 1858 283 284 1859 1860 1861 1862 1863 1864 1865 285 1866 1867 1868 +1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 286 287 288 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 289 290 291 292 293 1909 1910 1911 1912 1913 294 295 1914 1915 1916 1917 1918 1919 1920 1921 1922 +1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 296 297 298 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 299 300 1975 1976 1977 1978 1979 1980 1981 +1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 301 302 303 304 305 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 306 307 308 2034 2035 2036 2037 +2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 309 310 311 312 313 314 315 316 317 318 319 320 321 322 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 323 324 325 326 327 328 329 330 331 2075 2076 2077 2078 +2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 2104 2105 2106 2107 2108 2109 2110 2111 +2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 +2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 diff --git a/ioccc/2020/endoh1/prog.c b/ioccc/2020/endoh1/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..24e6cbdb407e727f188f4ddb5468435174f2f44f --- /dev/null +++ b/ioccc/2020/endoh1/prog.c @@ -0,0 +1,39 @@ + #include/**/<time.h> + #include <ncurses.h> + # include <stdlib.h> + /** */#define O()for(y-= !!\ + y;y<H&& /*...Semi-Automatic.*/y< p/W+2;\ + y++)for(x=p% W,x-=!!/*..MineSweeper...*/x;x<W&& x<p%W+2;x++) + #define _(x,y)COLOR_##x,COLOR_##y /* click / (R)estart / (Q)uit */ + #define Y(n)attrset(COLOR_PAIR(n)),mvprintw(/* IOCCC2019 or IOCCC2020 */ + typedef int I;I*M,W,H,S,C,E,X,T,c,p,q,i,j,k;char G[]=" x",U[256];I F(I p){ I + r=0,x,y=p/W,q;O()q=y*W+x,r+=M[q]^=p-q?(M[q]&16)<<8:0;return r;}I K(I p + ,I f,I g){ I x=(g+ f/256)%16-(f+g/256)%16,y=p/W,c=0,n=g/4096 + ,m=x==n?0:x==g /16%16-f/16%16-n?256:-1; if(m+1)O()if + ((4368&M[n=y*W +x])==4112){ M[c=1,n]=(M[n]&~16)|m; } + return c;}void D(){I p,k,o=0,n=C,m=0,q=0;if(LINES-1<H + ||COLS/2<W)clear (),Y(4)LINES/2,COLS/2-16,"Make the ter\ +minal bigger!");else{for (p=0;p<S;o+=k==3,Y(k)p/W+1,p%W*2,G),p++)G[1]="" +"_*!..12345678"[k=E?256&M[p ]?n--,2:E-2||M[p]%2<1?M[p]&16?q=p,m++,3:4+F(p)%16: +1:3];k=T+time(0);T=o||T>=0||E-1?T:k;k=T<0?k:T;Y(7)0,0,"%03d%*s%03d",n>999?999:n,W* +2-6,"",k>999?999:k);Y(9)0,W-1,E>1?"X-(":E-1||o?":-)":"8-)");M[q]|=256*(n==m&&n); } +refresh();}short B[]={_(RED,BLACK),_(WHITE,BLUE),_(GREEN,RED),_(MAGENTA,YELLOW),_( +CYAN,RED)};I main(I A,char**V){MEVENT e;FILE*f;srand(time(0));initscr();for(start\ +_color();X<12;X++){init_pair(X+1,B[X&&X<10?X-1:2],B[X?X<3?2:1:0]);}noecho();cbreak +();timeout(9);curs_set(0);keypad(stdscr,TRUE);for(mousemask(BUTTON1_CLICKED|BUTTO\ +N1_RELEASED,0);;){S=A<2?f=0,W=COLS/2,H=LINES-1,C=W*H/5,0:fscanf(f=fopen(V[A-1],"r" + ),"%d %d %d",&W,&H,&C)>3; ;S+=W*H;M=realloc(M,S*sizeof(I)*2);for(i=0 + ;i<S;i++)!f?M[i]=i,i&&(k=M[j=rand()%i],M[j]=M[i],M[i]=k):fscanf(f, + "%d",M+i);if(f)fclose(f);T=E=X=0;for(clear();D(),c=getch(),c-'r' + &&(c-KEY_RESIZE||E);){ if(c=='q'){ return(endwin(),0); }if(c== + KEY_MOUSE&&getmouse(&e)==OK&&e.x/2<W&&e.y<=H){if(!e.y&&(W-2<e.x&& + e.x<W+2)){break;}p=e.x/2+e.y*W-W;if(p>=0){if(!E){for(i=0;i<S;i++)M[S+M + [i]]=i,M[i]=16+(M[i]<C);C-=M[p]&1;M[p]=16;E=1;T=-time(0);}if(E<2)M[p]&=(M[p] + &257)==1?T+=time(0),E=2,273:257;}}for(p=0;p<S&&E==1;M[p++]&=273){}for(i= + (X+S-1)%S;E==1&&i!=X;X=(X+1)%S){if(!(M[p=M[X+S]]&272)){if(K(p,c=F(p) + ,0)){goto N;} for(k=p/W-2,k=k<0?0:k;k<p/W+3&&k <H;k++)for(j= + p%W-2,j =j<0?0:j;j<W&&j<p%W+3;)if (!(M[q= + k*W +j++]&272)){ if(K(p, c,F + (q))){ goto N; }F(q) + ; }F(p); }}N:; } } } + /*(c)Yusukse Endoh*/ diff --git a/ioccc/2020/endoh1/prog.orig.c b/ioccc/2020/endoh1/prog.orig.c new file mode 100644 index 0000000000000000000000000000000000000000..55721d089e7e72a36395927d2e375c4512e4649a --- /dev/null +++ b/ioccc/2020/endoh1/prog.orig.c @@ -0,0 +1,39 @@ + #include/**/<time.h> + #include <ncurses.h> + # include <stdlib.h> + /** */#define O()for(y-= !!\ + y;y<H&& /*semi-automatic----*/y< p/W+2;\ + y++)for(x=p% W,x-=!!/*-----minesweeper*/x;x<W&& x<p%W+2;x++) + #define _(x)COLOR_##x/*IOCCC2019IOCCC2019IOCCC2019IOCCC2019IOCCC20*/ + #define Y(n)attrset(COLOR_PAIR(n)),mvprintw/*IOCCC2019IOCCC2019IOCCC20*/ + int*M,W,H,S,C,E,X,T,c,p,q,i,j,k;char G[]=" x",U[256];int F(int p){int r=0,x, + y=p/W,q;O()q=y*W+x,r+=M[q]^=p-q?(M[q]&16)<<8:0;return r;}int K( int p, + int f,int g){int x=(g+f/256)%16-(f+g/256)%16,y=p/W,c=0,n= + g/4096,m=x==n ?0:x==g/16%16-f/16%16-n?256:-1;if(m+ + 1)O()if((M[n= y*W+x]&4368)==4112)M[n]=(M[n]&~16)|m + ,c++;return c; }void D(){int p,k,o=0,n=C;if(LINES-1< + H||COLS/2<W)/*| */clear(),Y(4)(LINES/2,COLS/2-16,"Mak\ +e the terminal window " "bigger!");else{for(p=0;p<S;o+=k==3,Y(k)(p/W+1 +,p%W*2,G),p++)G[1]="_*!.." "12345678"[k=E?M[p]&256?n--,2:E-2||M[p]%2<1?M[p]& +16?3:4+F(p)%16:1:3];k=T+time(0);T=o||T>=0||E-1?T:k;k=T<0?k:T;Y(7)(0,0,"%03d%*s%03\ +d",n>999?999:n,W*2-6,"",k>999?999:k);Y(9)(0,W-1,E>1?"X-(":E-1||o?":-)":"[-)");}re\ +fresh();}int main(int A,char**V){short B[]={_(RED),_(BLACK),_(WHITE),_(BLUE),_(GR\ +EEN),_(RED),_(MAGENTA),_(YELLOW),_(CYAN)};MEVENT e;FILE*f;srand(time(0));initscr() +;for(start_color();X<12;X++)init_pair(X+1,B[X&&X<10?X-1:2],B[X?X<3?2:1:0]);noecho( +);cbreak();timeout(9);curs_set(0);keypad(stdscr,TRUE);for(mousemask(BUTTON1_CLICK\ +ED|BUTTON1_RELEASED,0);;){if(A-->1){f=fopen(V[A],"r");fscanf(f,"%d %d %d",&W,&H,&C + );}else{f=0;W=COLS/2;H=LINES-1;C=W*H/5;}S=W*H;M=realloc(M,S*2*sizeof + (int));for(i=0;i<S;i++)!f?M[i]=i:fscanf(f,"%d",M+i);for(i=0;!f&&i< + S;i++)k=M[j=i+rand()%(S-i)],M[j]=M[i],M[i]=k;if(f)fclose(f);T=E= + X=0;for(clear();D(),c=getch(),c-'r'&&(c-KEY_RESIZE||E);){if (c + =='q')return(endwin(),0);if(c==KEY_MOUSE&&getmouse(&e)==OK&&e.x/ + 2<W&&e.y<=H){if(!e.y&&(W-2<e.x&&e.x<W+2))break;p=e.x/2+e.y*W-W;if(p>=0 + ){if(!E){for(i=0;i<S;i++)M[S+M[i]]=i,M[i]=16+(M[i]<C);C-=M[p]&1;M[p]=16;E=1; + T=-time(0);}if(E<2)M[p]&=(M[p]&257)==1?T+=time(0),E=2,273:257;}}for(p=0; + p<S&&E==1;)M[p++]&=273;for(i=(X+S-1)%S;E==1&&i!=X;X=(X+1)%S){if(!(M[ + p=M[X+S]]&272 )){if(K(p,c=F(p),0))goto N;for(k =p/W-2,k=k<0? + 0:k;k<H &&k<p/W+3;k++)for(j=p%W-2 ,j=j<0? + 0:j ;j<W&&j<p%W+3;j++)if (!( + M[q=j+k*W]&272)){if( + K(p,c,F(q)))goto N;F + (q);}F(p);}}N:;}}} diff --git a/ioccc/2020/endoh1/unwinnable.txt b/ioccc/2020/endoh1/unwinnable.txt new file mode 100644 index 0000000000000000000000000000000000000000..b6b22b6b167bd5a3d66e3ebdb036e93932bc45e3 --- /dev/null +++ b/ioccc/2020/endoh1/unwinnable.txt @@ -0,0 +1,6 @@ +5 5 4 +0 1 5 6 4 +2 3 7 8 9 +10 11 12 13 14 +15 16 17 18 19 +20 21 22 23 24 diff --git a/ioccc/2020/endoh2/Makefile b/ioccc/2020/endoh2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..62bed8c8f9b177a6c2738a8d206cbc66339d0720 --- /dev/null +++ b/ioccc/2020/endoh2/Makefile @@ -0,0 +1,590 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-comma -Wno-conversion -Wno-documentation -Wno-double-promotion -Wno-missing-prototypes \ + -Wno-missing-variable-declarations -Wno-redundant-parens -Wno-shadow -Wno-sign-compare \ + -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-sign-compare -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-sign-compare -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +#CSTD= -std=c11 +CSTD= -std=c99 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o +DATA= bear.txt hello.txt spoiler.zip yoda.txt +TARGET= prog +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/endoh2/bear.txt b/ioccc/2020/endoh2/bear.txt new file mode 100644 index 0000000000000000000000000000000000000000..9cfb14ec19cd26f0055074323cbff4d9716b3c99 --- /dev/null +++ b/ioccc/2020/endoh2/bear.txt @@ -0,0 +1,7 @@ +GUR +BGURE +QNL + +V +ZRG +LBQN diff --git a/ioccc/2020/endoh2/compile_commands.json b/ioccc/2020/endoh2/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..90a3a37a1771f042534030a645c049e374015d97 --- /dev/null +++ b/ioccc/2020/endoh2/compile_commands.json @@ -0,0 +1,20 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c99", + "-Wall", + "-Wextra", + "-pedantic", + "-Wno-sign-compare", + "-Wno-unknown-warning-option", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/endoh2/hello.txt b/ioccc/2020/endoh2/hello.txt new file mode 100644 index 0000000000000000000000000000000000000000..b5caa71c92132e0dc09fe4473386d089570a443c --- /dev/null +++ b/ioccc/2020/endoh2/hello.txt @@ -0,0 +1,4 @@ +URYYB +JBEYQ +NAQ +TNYNKL diff --git a/ioccc/2020/endoh2/hint.text b/ioccc/2020/endoh2/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..b2dceef279db9a8ab78cb4e842738cbcaf72690f --- /dev/null +++ b/ioccc/2020/endoh2/hint.text @@ -0,0 +1,54 @@ +# Best perspective + +Yusuke Endoh +Twitter: @mametter + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + + make + ./prog + +### Try: + + ./prog + + ./prog hello.txt + + ./prog yoda.txt + + ./prog bear.txt + +### Selected Judges Remarks: + +Clever use of the C99 complex data type. The spoiler.zip file contains clues +as to how some winning authors create / edit programs into ASCII shapes. + +With the source from the spoiler.zip file could you make the code render for a +larger terminal window? How about adding more glyphs? + +## Author's comments: +No! Try not. Do, or do not. There is no try. + + $ gcc -std=c99 prog.c + $ a.out + $ a.out hello.txt + $ a.out yoda.txt + $ a.out bear.txt + +See spoiler.zip for the source code. +[The 16th most common password on the Internet in 2017 (according to Splash Data)][1] the password is. + +[1]: https://en.wikipedia.org/wiki/List_of_the_most_common_passwords + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/endoh2/prog.c b/ioccc/2020/endoh2/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..8a46fe05825e8ff1be8d1d0c7ff551e379b10799 --- /dev/null +++ b/ioccc/2020/endoh2/prog.c @@ -0,0 +1,28 @@ + /* A long time ago in a galaxy far, far away.... */ + +int*d,D[9999],N=20,L=4,n,m,k,a[3],i;char*p,*q,S[2000]="L@X-SGD-HNBBB-AD-VHSG-\ +-XNT\x1b[2J\x1b[H",*s=S,*G="r2zZX!.+@KBK^yh.!:%Bud!.+Jyh.!6.BHBhp!6.BHBh!:%Bu\ +v{VT!.hBJ6p!042ljn!284b}`!.hR6Dp!.hp!h.T6p!h.p6!2/LilqP72!h.+@QB!~}lqP72/Lil!\ +h.+@QBFp!:)0?F]nwf!,82v!.sv{6!.l6!,j<n8!.xN6t!&NvN*!.6hp";/*Stay_on_target.**/ +#include/**/<complex.h>/**//*Oh,my_dear_friend.How_I've_missed_you.--C-3PO***/ +typedef/**/complex/**/double(c);c(X)[3],P,O;c/**/B(double t){double s=1-t,u;P= +s*s*X[1] +2 *s*t* *X+t *t*X [2]+O;u=I*P; +return+48*(( s=P)+ 48*I )/( 1<u? u: 1);} /* 1977 IOCCC2020*/ +#include/** Do.Or do_not . There_is_ no_try... --Yoda**/<stdio.h> +void/**/b( double t,/*** * **/double u){double s=P=B(t)-B(u);(s=P +*(2*s-P)) <1?m=P=B ((t+ u)/ 2),k =- I*P, m> -41&&m<39&&9<k&&k +<48? m+=k/ 2*80+ 73,S [m]= S[m] +-73?k%2?S[m]-94?95:73:S[m]-95?94:73:73:1:(b(t,(t+u)/2),b((t+u)/2,u),0);}/*<oo> +_No. _I_am_ IOCCC 1977 ***/ +#include/***** your father.. --DarthVader **/ <time.h>/**** ****/ +int(main)(int (x), char**V){; clock_t(c)= /* */clock();;; for(d=D +;m<26;m++,s ++)*s> 63?*d++=m% 7* 16-7 *8,*d++=m/ 7*25,*d++ +=*s-64:0;; if(V[1]) {;;;FILE *F =fopen(V[+1], "r");for (d=D,L=N=m +=0;(x=/** * *** **/ fgetc(F))>0 +||fclose(F);)if(x>13?64<x&&x<91?*d++=m*16,*d++=L*25,*d++=x%26:0,m++,0:1)for(++ +L;d-D>N*3||(m=0);N++)D[N*3]-=m*8;}for(;i<200+L*25;i++){for(n=0,p=S+33;n<1920;* +p++=n++%80>78?10:32){}for(*p=x=0,d=D;x<N;x++,d+=3){O=(d[1]-i-40)*I+*d;n=d[2];p +=G;for(;n--;)for(;*p++>33;);*a=a[1]=*p++;for(;*p>33;p++)if(*p%2?*a=*p,0:1){a[2 +]=*p;for(m=0;m<3;m++){k=a[m]/2-18;q="/&&&##%%##.+),A$$$$'&&'&&((%-((#'/#%%#&#\ +&&#D&";for(n=2;k--;)n+=*q++-34;X[m]=n%13+n/13*I;}b(0,1);*a=a[1]=*p;}}for(puts( +s),s=S+30;(clock()-c)*10<i*CLOCKS_PER_SEC;);}return 0;}/*Nevertellmetheodds*/ diff --git a/ioccc/2020/endoh2/spoiler.zip b/ioccc/2020/endoh2/spoiler.zip new file mode 100644 index 0000000000000000000000000000000000000000..29b5418074142cdc260f235e56d6542b338c937c Binary files /dev/null and b/ioccc/2020/endoh2/spoiler.zip differ diff --git a/ioccc/2020/endoh2/yoda.txt b/ioccc/2020/endoh2/yoda.txt new file mode 100644 index 0000000000000000000000000000000000000000..750d110c06da0df6f614e4e97ec833fabf61b40f --- /dev/null +++ b/ioccc/2020/endoh2/yoda.txt @@ -0,0 +1,14 @@ +NATRE +SRNE +NTTERFFVBA + +GUR +QNEX +FVQR +BS +VBPPP +NER +GURL + + +LBQN diff --git a/ioccc/2020/endoh3/Makefile b/ioccc/2020/endoh3/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..87d00d97514bf4fc619eba410a64d82ac005d410 --- /dev/null +++ b/ioccc/2020/endoh3/Makefile @@ -0,0 +1,602 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-date-time -Wno-float-conversion -Wno-implicit-float-conversion -Wno-missing-prototypes \ + -Wno-missing-variable-declarations -Wno-redundant-parens -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +CSTD= -std=c11 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o +DATA= +TARGET= prog clock.c clock run_clock +# +ALT_OBJ= +ALT_TARGET=prog.alt + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +prog.alt: prog.alt.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +clock.c: prog.c + @${RM} -f $@ + ${CP} -f $< $@ + +clock: clock.c + @${RM} -f $@ + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +run_clock: run_clock.sh + @${RM} -f $@ + ${CP} -f $< $@ + ${CHMOD} +x $@ + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/endoh3/compile_commands.json b/ioccc/2020/endoh3/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..01f2d5a568816df61b9b52948d6de09e4dbb2c14 --- /dev/null +++ b/ioccc/2020/endoh3/compile_commands.json @@ -0,0 +1,34 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-O3", + "-o", + "clock", + "clock.c" + ], + "directory": ".", + "file": "clock.c" + }, + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/endoh3/hint.text b/ioccc/2020/endoh3/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..81af15b5af374cbc18190b21943a6d1eb67be393 --- /dev/null +++ b/ioccc/2020/endoh3/hint.text @@ -0,0 +1,44 @@ +# Most head-turning + +Yusuke Endoh +Twitter: @mametter + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog + +### Try: + + ./run_clock + # And watch closely for 15-20 seconds + +### Selected Judges Remarks: + +You may be tempted to use a mirror. Resist the temptation! Try figuring out how the clock hands are drawn. +Can you change the program to make it draw a familiar (non-mirrored) clock face? Can you add the second hand? + +When using the `run_clock` shell script, your perception of time might depend on what time it is. + +## Author's comments: +Prepare a mirror! + + $ make clock + +Note: You need to recompile it each run. + +--- + +prog.alt.c is an alternate version that uses Unicode letters, which was suggested by the judges. + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/endoh3/prog.alt.c b/ioccc/2020/endoh3/prog.alt.c new file mode 100644 index 0000000000000000000000000000000000000000..6f64c5dd80bbb04c2a0d32f64c52c533f0b82c0d --- /dev/null +++ b/ioccc/2020/endoh3/prog.alt.c @@ -0,0 +1,23 @@ +#define/**/Q(x,y)r;char*q/* */=y#x","#y")",*p,x=*p%67;} + /*-IOCCC2020-*/#include/* */<stdio.h>/*-BBQlock--*/ + int(y),x,i,k,Q(s[9<<9/* 12 */];float(f)[3];void(Z) + (){*f=r<0?r:-r;f[1]/* 11 1 */=42.5;f[2]=22.5;for + (k=0;++k<39;*f/=(k/* 10 2 */%2?k:-k)*6875.5/i) + y=f[1+k%2]+=*f;k=/* */f[2];p=s+k/2*86+y + ;}int(main)(){p=/* 9 o-------> 3 */s;for(;i<1978;*q + >32?k=i++/86-11/* / */,y=(750>r*r+k*k + *4)*4+y/2,*p++=/* 8 L 4 */r<44?y?"+0X+0X" + "+!"[y]-1:*q++/* 7 5 */:10:*q++)r=-41 + +i%86;r=20;for/* 6 */(x=13;(i=3600* + --x);*p++="XR"/* */"MOQSUWAY"[x%+ + 10]-9,*p+=x/10/* */*41)Z();sscanf + (__TIME__,"%d"/* \ / -------+ */":%d:%d",&k,&x + ,&i);r=10;for(i/* \ / ------ | */+=(k*60+x)*60;r + +18;*p=k%2?*p%2/* \ / ------ | */?59:44:*p>39?59 + :39,i=r--?i:i%(+/* \ / ------ | */3600)*12)Z();for + (p=s;*p;putchar(k/* X ------ | */%2&&k<14?q="End", + printf("%c%c",224|/* __/ \__ | | */(21554>>k&3),"gCS" + "gGMX"[k/2]+65),"E"/* / \ / \ | | */"Gh_BrG"[k/2]+64:*p + ),++p)k,"#define/**/"/* \__/ \__/ +--+ */"Q(x,y)r;cha""r*q=y#" + "x\",\"#y\")\",*p,x=*p"/* */"%67;}/*-IOCCC2020-*/#" +"include<stdio.h>/*-BBQl"/* */"ock--*/int(y),x,i,k,Q(") diff --git a/ioccc/2020/endoh3/prog.c b/ioccc/2020/endoh3/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..c197ec964b633c5d860f0ed73003edecf1f77a07 --- /dev/null +++ b/ioccc/2020/endoh3/prog.c @@ -0,0 +1,23 @@ +#define/**/Q(x,y)char*/* */q=y#x","#y")",*p,s[x;} + /*IOCCC'20*/#include/* */<stdio.h>/*-Qlock-*/ + int(y),x,i,k,r;Q(9/* 12 */<<9];float(o)[03]; + void(P)(){*o=r<0/* 11 1 */?r:-r;o[1]=39.5; + o[2]=22.5;for(k/* 10 2 */=0;++k<39;*o*=i + /6875.5/(k%2?k/* */:-k))y=o[1+k%2 + ]+=*o;k=o[2];/* 9 o-------> 3 */p=s+y+k/2*80; + }int(main)()/* / */{for(p=s;+i< + 1839;*q>32?k/* 8 L 4 */=i++/80-11,y + =(750>r*r+k/* 7 5 */*k*4)*4+y/2 + ,*p++=r<41?/* 6 */y?"0X+0X+!" + [y-1]-1:+*q/* */++:10:*q++) + r=i%80-38;;/* */;for(x=13,r + =20;i=3600*/* \ / -------+ */--x,i;*p++= + "OISEA2dC8e"/* \ / ------ | */[x%10],*p+=x + /10*41)P();r/* \ / ------ | */=10;;sscanf( + __TIME__,"%d"/* \ / ------ | */":%d:%d",&k,& + x,&i);for(i+=(/* X ------ | */k*60+x)*60;18+ + r;*p=k%2?*p%2?+/* __/ \__ | | */59:44:*p>39?59: + 39,i=!r--?i%3600/* / \ / \ | | */*12:i)P();puts(s + ),"#define/**/Q(x"/* \__/ \__/ +--+ */",y)char*q=y#x\"," + "\"#y\")\",*p,s[x;}"/* */"/*IOCCC'20*/#inclu" +"de<stdio.h>/*-Qlock-"/* */"*/int(y),x,i,k,r;Q(") diff --git a/ioccc/2020/endoh3/run_clock.sh b/ioccc/2020/endoh3/run_clock.sh new file mode 100755 index 0000000000000000000000000000000000000000..0cef2c16c72b583d0635b87a1818ad96c85fd6a4 --- /dev/null +++ b/ioccc/2020/endoh3/run_clock.sh @@ -0,0 +1,7 @@ +#!/bin/sh +while true; do +cc -std=c11 -Wall -Wextra -pedantic -O3 clock.c -o clock +clear +./clock | tee clock.c +sleep 5 +done diff --git a/ioccc/2020/ferguson1/COMPILING b/ioccc/2020/ferguson1/COMPILING new file mode 100644 index 0000000000000000000000000000000000000000..5f503bf818a80b1fa665f085a1d3104870e11c7f --- /dev/null +++ b/ioccc/2020/ferguson1/COMPILING @@ -0,0 +1,94 @@ +In order to successfully compile this you will need a C compiler that supports +C99+ and ncurses; note that for some platforms (e.g. Red Hat based Linux) you +will need two different packages: the library itself but also the dev package +that has the header files etc. If you use the Makefile obviously you need `make' +too. + +In gameplay.markdown I show how to easily customise the colours, set up +different gameplay modes and various other things. The troubleshooting.markdown +and terminals.markdown as well as bugs.markdown include a variety of information +should you run into trouble. + +-- + +# Portability + +I have tested this under macOS Catalina, Fedora (29 and also 31 - no that's not +a typo, I upgraded from 29 to 31 as I had delayed upgrading to 30 due to a +number of issues and being busy) and CentOS 7.7.1908. It obviously requires +ncurses but other than that nothing extra should be needed. Note that the +testing of Fedora 29 was earlier in the development however (but then 29 is also +EOL). + +Furthermore I do not believe - but I cannot confirm either - that endianness +matters; I only have Intel CPUs. + +I imagine that it works for 32-bit systems but I do not know for sure. + + +# Portability: macOS + +You should be able to get the compiler with: + + sudo xcode-select --install + +You don't need Xcode itself and it appears that the command line tools (as above +should install) already has ncurses so there shouldn't be anything else that +needs to be done. But I'm not actually sure of this - I'm seeing conflicting +information and it's been too long; anyway there's always [MacPorts][] and also +Homebrew which should be sufficient; I do *NOT* recommend Homebrew however: +it takes ownership of /usr/local: as in the user you run it as is the new owner +so that you don't need sudo because ... Well never mind. + + +# Portability: Fedora + +You'll need the packages `gcc`, `ncurses` and `ncurses-devel` (plus `make` if +you want to use the Makefile) to compile and link this entry. With Fedora more +recent versions there's the `dnf` package manager but I cannot help with any of +the GUI installers since I don't use them. Something like: + + sudo dnf install ncurses-devel ncurses make gcc + + Or + # dnf install ncurses-devel ncurses make gcc + +# Portability: CentOS + +Just like Fedora you will need `gcc`, `ncurses`, `ncurses-devel` (and if you +want to use the Makefile `make`). CentOS uses `yum` and CentOS 8 uses `dnf`. +So: + + sudo yum install ncurses-devel ncurses make gcc + + Or + # yum install ncurses-devel ncurses make gcc + +Or + sudo dnf install ncurses-devel ncurses make gcc + + Or + + # dnf install ncurses-devel ncurses make gcc + + +You can also use Clang to compile. + + +# Compilation notes + +As long as you have the dependencies above the only thing that comes to mind is +integer width problems. + +If `size_t` does not equate to unsigned long: In this case if say it's an +unsigned long long then theoretically you should be able to change the +`strtoul()` to be `strtoull()` (after updating the typedef for unsigned long to +be unsigned long long maybe?). It appears to work from a quick test at least. + +If it's an unsigned int I believe you will have to opt for an unsigned long (so +`strtoul()` cast to an unsigned int). + +Anything else I do not know other than just changing the typedef and updating to +the proper function (and/or cast to the right type). + +[MacPorts]: https://www.macports.org diff --git a/ioccc/2020/ferguson1/HACKING b/ioccc/2020/ferguson1/HACKING new file mode 100644 index 0000000000000000000000000000000000000000..0a673048903976147af2b046e4d58c069bc4e0ac --- /dev/null +++ b/ioccc/2020/ferguson1/HACKING @@ -0,0 +1,501 @@ +# WARNING: There are some things cited in this document that are no longer +# correct, might be misleading or otherwise not clear. This is both intentional +# and unintentional. This is especially true for claims that something means +# something specific. Put another way just because the table says something +# doesn't mean it's the whole truth: no misleading comments but misleading +# document that talks about some parts of the code! + +In this document I provide information to the herpetologist hackers to help them +to modify certain things and add features for their studying of snakes. Or if +you prefer you can be the snake studying the herpetologist. Whichever character +you prefer to play doesn't really matter. + +Please do not assume that just because something is in this file means that it's +complete or will work without any changes. As I have changed the game over +development stages some features have been dramatically changed and some of +these ideas could be incompatible now or otherwise impractical. Also you might +find in fact that some of these leave more questions than answers (e.g. some +require making decisions for specific problems one might encounter)! + +With that said here's the C sibilancy (the herpetologist programmer's and +snake's syllabary) for all snake and herpetologist programmers alike. + + +* Modifications + + - Modifying the colours + - Background colour + + - Modifying the characters for the wall, bug and snake + + - Modifying input keys + + - Modifying the status/score line + + - Make it so the snake starts at a random location + +* Additions + + - Health (and/or Lives) + + - Saving the game + + - Different types of walls + - Blockades + + - Diagonal movement + + - Special abilities + + - Obstacles + + - More than one bug + + - Power-ups + + - Snakeskin shedding (becoming an obstacle) + + - Snake moves faster over time + + - Max times the bug evades before game over + +* MODIFICATIONS + +Here I include information on modifying the game in various ways depending on +the preference of the herpetologist (or if you prefer you can be the snake +studying the herpetologist). + + +# Modifying the colours + +As I already said I provided a script that prompts you for colours and then +compiles the game with those colours (default if invalid input). + +The parts of the game that are coloured are the WALL(s), the snake HEAD and +snake BODY. In the published alternate version (prog.alt.c) the bug is also +colourable. This means that there are a total of four configurable colour pairs. +It only supports the eight standard colours. Each colour is a pair: foreground +and background. + +To change the colours use the snake-colours.sh or play.sh scripts. Hit enter for +defaults if you don't want to change the colour. + +# Background colour of the game field + +I prefer black backgrounds but this is the basic idea behind changing it. You +initialise a pair (make it 5 so as to not interfere with the script +customisability) and then you use the bkgd() function with the colour pair. +Something like this: + + init_pair(5, COLOR_BLACK, COLOR_WHITE); + bkgd(COLOR_PAIR(5)); + +I played with this after winning and I came across some problems with colours +but that changes the background of the program anyway. + +The standard colour identifiers are: + + COLOR_BLACK + COLOR_RED + COLOR_GREEN + COLOR_YELLOW + COLOR_BLUE + COLOR_MAGENTA + COLOR_CYAN + COLOR_WHITE + + +See Linux Journal for more information: + + https://www.linuxjournal.com/content/programming-color-ncurses for more details). + + +# Modifying the characters for the wall, bug and snake + +For the wall, bug and snake body characters you can replace the following in the +source code (include the single quotes) respectively: + + '#' + + '*' + + 'o' + +# Modifying input keys + +Let's say you don't want to use arrow keys or you don't have arrow keys. Instead +you might want the keys 'l', 'r', 'u' and 'd' for the directions. Find the case +statements: + + KEY_LEFT + KEY_RIGHT + KEY_UP + KEY_DOWN + +Replace KEY_LEFT with: + + 'l' + +(Yes the single quotes matter) + +And do the same thing for the other directions too. If you want more than one +key e.g. the arrow keys and the letters just add another case statement e.g. for +left it might be: + + case KEY_LEFT: case 'l': + + +You can do similar for the other input keys. Please note that modifier keys like +ctrl aren't detectable or at least I'm unaware of how to do so. + + +# Modifying the status/score line (table of variables/stats below) + +* SPOILER WARNING + +Below I give a table of some variables/expressions along with the data types and +their respective format specifiers of the data. Originally it was a lot more +detailed but as I started obfuscating things variables started to disappear and +I decided to remove those variables from the table outright. Again also remember +that it's outdated. + +Please note that this set of information is the same that will be seen at the +end of the game; I leave that as an exercise to the reader to implement two +different sets. Please also be aware that if you don't want any information you +must set it to the below at the very least; defining it without a value is not +enough (it amounts to the parameters to a printf call): + + #define J " " ); + +If you don't care about brief displays of 'o' at 0,0 you can just have: + + #define J ""); + +That's the bare minimum. Notice also that it's been a long while since I've +tested this part but I think this is right. + +Anyway as I said the score line has basic statistics that's relatively easy to +change if you want more or less or different information e.g. the location of +the bug. + +Initially there was no display of where the (head of the) snake was at nor the +maximum size (that is the size calculated by ncurses) - though the astute hacker +would notice that the maximum dimensions size is not what the status line says: +this has to do with the walls and the status line - coordinates. + +At that point the only time the top stats were updated is when the snake got a +bug. This however was something I didn't quite like: I like having the +coordinates of where the snake is plus the other things that are there (a number +of which were added over time). Obviously this would take many bug sized bytes +(bites) even once let alone twice! Thus I made it into a define: + + #define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n), Y, y[-2], X,*y,A,g, c); + +With the table below you can show a variety of other variables/statistics. + +There's another reason for changing this line though: depending on the terminal +width the line could cover the top wall; this can even happen only part of the +game because the line length is not constant: most of the variables change +throughout the game play and as these are displayed the length of the line +changes. Use `make test' to get an estimate (it's not perfect). + +This is not the fault of my entry but rather how text wraps. But this is another +reason it's easy to change: if the terminal size is too short then you can +update it; but if you want additional or different information you can also +update it. Remember that if you modify the score data the termcaps algorithm +might not remain as correct! + +But the game needs to have the walls drawn and the score line is also important; +well it's important in that the row number of the top wall is in fact used and +so if this line wasn't there it would require changes to make it work right. + +For an example this would only include the size of the snake and the number of +bugs eaten (I think I have this correct; I've made many changes to the point of +not wanting to mess with anything that's unnecessary): + + #define J Z(SIZE: %zu BUGS: %zu\n), A, c); + +More generally the following expressions and data types (with format specifiers) +come to mind as information that might be of interest. + + DESCRIPTION EXPRESSION TYPE FORMAT NOTES + SPECIFIER + + Snake size A size_t %zu + + Y coordinate Y int %d + of snake head + + X coordinate X int %d + of snake head + + Max snake size g size_t %zu + + Bugs eaten c size_t %zu + + Bug line (Y) *U int %d + + Bug column (X) *V int %d + + (Initial) Snake size A size_t %zu + + Growth size (per N size_t %zu + bug) + + +# Make it so the snake starts at a random location + +Quite simply change: + + X = H / 2; Y = *x / 2; + +To be something like: + + X = R(1,H-1); + Y = R(2,*x-1); + +Or whatever you might want it to be... (question to answer: will this work at +all? You decide!) + + +* ADDITIONS (+) + +Here are some things you could add (including a bit of code). + + +# Health (and/or Lives) + +This was something I thought of a number of times but I opted for other features +instead. Here are some ideas on how one might choose to implement something like +this. Or maybe it's more like what sorts of things do you have to consider and +answer? + +(1) If the snake runs back into itself - thus dying - the snake would actually +be slithering inside itself (a rather creepy thought - though they sort of do +when they shed their skin). How then would the lives be of any value? If that +would constitute as running into itself wouldn't it very quickly lose all lives? + +I can think of a number of ways to answer this question: by defining specific +rules (as in what would be allowed and what wouldn't be) and also by when to +decrement the lives. + +(2) If the snake hits a wall and it's not allowed to where would the snake be +placed? This is similar to (1) but maybe not as many things to consider. + +(3) Should the snake lose its size? WHAT does having another life even MEAN? + +(4) Do you want (you do not necessarily need) a new variable that says how many +lives you want? Either way probably be good that it can be specified by the +player. + +The simplest rules I can think of off the top of my head is that the snake loses +its size but it keeps the bugs count. So if the lives are three and the snake +has three lives, has eaten 15 bugs and then runs into itself it will start out +again at the original size (remember there's a fair bit more than just changing +the size of the snake to do in order for it to be of use!) but it then the next +bug it eats will be the 16th bug. + +Of course you could also say that the first time the snake eats a bug (on the +next life) it grows to the size it once was. This would actually be one way to +deal with some issues that I sort of alluded to above. Of course it also has +some other complications. + +You could do similar for health only maybe the size of the snake decreases or +you use the variable you would have used for lives to be health instead. + +Vital issue to resolve: Where is the snake? And if the snake size is decreased +will you be careful enough that you don't run into the snake where it actually +isn't? + + +# Saving the game + +A few things would have to be done to do this. Maybe more than a few: some +decisions and some code. + +First obviously is you would need a hook to save the game: that is what if you +don't want to save? You could save every time the snake moves so that you keep +the highest size (though this could theoretically slow the game down more as the +snake gets bigger and bigger). Or you could say that hitting the key 's' saves +the game by calling a save function. + +Second is you need a save function. You would need to save the dimensions of +the game, all the coordinates the snake is currently at (from head to tail), +where the bug is, decide whether or not to save the direction (if it's 0 the +snake isn't moving which would mean the player could decide when to resume) and +the number of bugs eaten so far. Alternatively you could have the bug simply be +placed somewhere where the snake isn't after replacing (can you replace +something with itself?) the snake. + +Question: Do you have to save the WALLS and other environmental variables? +You wouldn't have to but you could: If you didn't it would mean that the player +could change the growth size on another run for example, or they could disable +or enable a feature. + +Of course you would also need a restore routine. This would mean you would want +to parse the command line so as to know which file should be read in (easiest +way would be if the first arg is some value then it tries to load in whatever +you decided to name the save file). How would this work? + +You would have to make sure that the dimensions of the terminal are valid for +what was saved and you would have to compensate that maybe the dimensions have +to be slightly adjusted for the screen (I have given more than enough +information on this elsewhere as to why this is). Obviously you have to +initialise ncurses, allocate the arrays, draw the walls, snake, bug etc. You +wouldn't initialise ncurses or its features more than once (i.e. keep track of +whether or not you have initialised these things due to a file being read or +starting anew). Clearly you would have to come up with a file format and have +error detection too. I can think of an easier way to make sure you don't +initialise the ncurses twice however. It would do the same things only with a +bit less code and maybe simpler logic. + +It might seem like a difficult task but it's actually not that difficult. It +didn't take much time for me to do something like this: as far as saving and +loading the values and even setting up ncurses: I just didn't go beyond that. + +Tip: Don't try scr_dump()/scr_restore()/scr_init()/scr_set(). After a quick +test in the way I have things set up it seems to cause some problems (also +scr_dump() quits the program). + +You would have to instead identify that restoring is requested, then read in the +file (including the coordinates) and then populate the snake arrays, drawing it +on screen. + + +# Different types of walls + +The game has two modes with walls: if you run into it the game is over (you +die) OR you go through it and come out on the opposite side. There certainly are +other possibilities though. Here I give some ideas that could be implemented +(and one I have some code for). + +# Different types of walls: Blockades + +Instead of the snake either dying or going through and out on the other side +what if it's just that the snake is momentarily dazed and unable to move again +until it comes round sort of like what happens with some people who pay more +attention to their ruddy phone instead of where they're walking (even when +crossing a busy street!). + +If you look at the walls code you will see a ternary operator for both X and Y +coordinates. This of course is very different now but the idea remains the same: + + if (p && !(*O>=O[1]||H>=M(1))) + { + if (X<1||X>=H) + X = X<1?H-1:1; + if (Y<2||Y>=*O) + Y = Y<2?*O-1:2; + } + + +You can ignore the first if if you like; I'm not going to explain that part. The +inner if statements however are testing if the new snake coordinates are beyond +the walls (off screen). Depending on where the snake is it will set the +coordinates to the correct new location. + +If however you wanted the walls to act as a barrier you could do something like +this instead (omitting the inner if statements here): + + X=X<1?1:*H-1; + + Y=Y<2?2:*O-1; + +Again though that's just the idea; the code is dramatically different. The above +incidentally is not even complete. + +You could also have it so depending on the WALLS value have it go through +walls, end game or act as a blockade. If you really wanted you could have some +walls you can go through and some you can't (maybe different colours would be +needed?). + +Oh and yes you might find it can look a bit funny this way. For instance if +you're slithering left along top wall and you hit up the snake will still be +horizontal (after the thing I warned about is resolved of course! - And that's a +very important one unless you want negative coordinates - and you don't!) since +it'll have stopped. If you were to then hit the direction you had been going you +will see that it continues going that way in a straight horizontal line. In +other words the snake will just appear to be not moving as if the game had been +paused. + + +# Diagonal movement + +I said this is impractical so how could it be done? Well you have to decide +which keys would take you up and right, up and left, down and right or down and +left. The trouble is ncurses can't detect both right and up at the same time. +Besides that though it would only be a matter of updating both Y and X +coordinates rather than just one or the other. That's easy enough to do. The +only impractical part of this is deciding the keys and unfortunately rule 2b +(and probably 2b) would have been broken and so have no chance of winning (now +that I won it's too much effort and I've forgotten some of the stuff too to say +nothing of getting the format right). + +Anyway it's just a matter of updating both X and Y. But what about going through +walls mode? Does it matter? I'll let you figure it out! + +# Special abilities + +Could the snake jump over itself if it wanted to? How would this be implemented? +The head would simply be moved one beyond but then you would have to keep track +of where the part that was jumped over is and what part of the snake has to do +the same thing. I can think of a much easier way though. This very paragraph +actually includes it! Then it would only be a matter of deciding what key does +what. + + +# Obstacles + +Similar to walls only that it's inside the field. You would have to consider +the behaviour of running into the obstacles: should the snake die? Should it +lose health/lives (if implemented)? Can it go through them? And also: the bug +placement would have to be updated too. You would also need to figure out what +character to use for the obstacles: I personally would just reuse the wall +character. Also to make it simpler if the walls are passable then so too would +be the obstacles; else you would die (or if you had health/lives then those +would apply). + +# More than one bug + +The main thing to consider would be the test if the snake has eaten a bug would +have to check an array (and: how big? Where does the size come from?) as well as +the placement routine (though I guess you could have a value for each array +meaning that if you run into a bug spot that has more than one bug you would eat +that many bugs). + + +# Power-ups + +You would need to decide what power-ups exist, what they do, how many can there +be (and how many can the snake have at one time), what makes them show up plus +you would have to add code to handle the power-ups. + + +# Snakeskin shedding (becoming an obstacle) + +I.e. at some point the snake would split back to some (arbitrary) size but then +the snakeskin left would act as the snake in the sense that if the snake runs +into it it's the same as running into the snake. More realistically the +snakeskin would be the same size the snake was and the snake would grow as it +slithered out. But that would fill the screen very quickly of course. Maybe the +snakeskin has some other purpose? + + +# Snake moves faster over time + +In the game Surround you have no control over the speed. I believe there are +five different speed levels but the player has no control over it except the +drawing mode. It would be possible to make it so the snake moves faster over +time. How often and by what amount would probably vary but importantly it would +need to not go so fast there's no controlling - or go below 0 which puts it in +blocking mode. Probably it would be that it gets faster up to a certain per cent +of the original speed so that it doesn't get too fast. But even that would have +to be customisable. + +# Max times the bug evades before game over + +Basically so that the player is on a time schedule of sorts. The same could be +done for maximum number of movements before game over. These would both be +rather easy to implement but personally I would only consider the max number of +evasions (I just don't have many more bytes left!) - unless maybe that there is +no default limit on max moves. diff --git a/ioccc/2020/ferguson1/Makefile b/ioccc/2020/ferguson1/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..97359f881ece50ce58794dee0fc79fbcb60ceaed --- /dev/null +++ b/ioccc/2020/ferguson1/Makefile @@ -0,0 +1,622 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-unused-value -Wno-implicit-fallthrough -Wno-parentheses \ + -Wno-binding-in-condition -Wno-binding-in-condition -Wno-misleading-indentation \ + -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +CSILENCE= -Wno-unused-value -Wno-misleading-indentation -Wno-parentheses \ + -Wno-unknown-warning-option +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +CSTD= -std=c11 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +#CDEFINE= +#CDEFINE= -DIOCCC +CDEFINE= -D_XOPEN_SOURCE -D_POSIX_C_SOURCE -D'f(a,b)'='((a)<(b)?(a):(b))' -DWALL='COLOR_CYAN' \ + -DHEAD='COLOR_RED' -DBODY='COLOR_GREEN' -DWB='COLOR_BLACK' -DHB='COLOR_BLACK' -DBS='COLOR_BLACK' \ + -DBG='COLOR_WHITE' -DBB='COLOR_BLACK' + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +#LIBS= +#LIBS= -L ${X11_LIBDIR} +LIBS= -lcurses + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +#CC= gcc +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o termcaps.o +DATA= COMPILING HACKING bugs.markdown cannibalism.log \ + chocolate-cake.markdown crazy.log gameplay.markdown \ + judges.markdown snake-colours.sh snake.1 spoilers.markdown \ + termcaps.c terminals.markdown troubleshooting.markdown +TARGET= prog snake snake-colours play snake-colours termcaps ${ALT_TARGET} +# +ALT_OBJ= +ALT_TARGET=prog.alt + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + @-if [ ! -f "$@" ]; then \ + ${ECHO} "Tip: Use the snake-colours script to easily configure colours and play"; \ + ${ECHO} "Tip: Use the play script to easily play several preset game modes"; \ + fi + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +snake: prog + @${RM} -f $@ + ${LN} -f -s $? $@ + +termcaps: termcaps.c + ${CC} ${CFLAGS} -Wno-padded -Wno-incompatible-pointer-types-discards-qualifiers $< -o $@ ${LIBS} + +play: play.sh + @${RM} -f $@ + ${CP} -f $? $@ + ${CHMOD} +x $@ + +snake-colours: snake-colours.sh + @${RM} -f $@ + ${CP} -f $? $@ + ${CHMOD} +x $@ + +# alternative executable +# +${ALT_TARGET}: prog.alt.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + @${RM} -f snake.alt + ${LN} -f -s prog.alt snake.alt + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all ${ALT_TARGET} + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} snake.alt + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + ${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +test: termcaps + @./termcaps + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + ${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + ${ECHO} 'haste' + @${TRUE} + +make: + ${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + ${ECHO} you expected to often mis-understand this $${RANDOM} magic + ${ECHO} chongo '<was here>' "/\\oo/\\" + ${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + ${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + ${ECHO} $@ is a dwarf planet + ${ECHO} dwarf is a type of planet + ${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + ${ECHO} $@ is a dwarf planet + ${ECHO} dwarf is a type of planet + ${ECHO} therefore, $@ is a planet + ${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/ferguson1/bugs.text b/ioccc/2020/ferguson1/bugs.text new file mode 100644 index 0000000000000000000000000000000000000000..26aa2305b8a51c530d2ec7768bbd4946a1c79e26 --- /dev/null +++ b/ioccc/2020/ferguson1/bugs.text @@ -0,0 +1,303 @@ +Current bugs and things that look like bugs but are not, as of 12 September 2020. + +<a name="toc"></a> +- [Built-in test unit for some features!](#builtin-test-unit) +- [The snake doesn't seem to be moving](#stillsnake) +- [getch() also accepts input from some input hardware other than keyboards](#getch) +- [SIZE=0 is the same as SIZE=1 and other oddities](#size) +- ['I was a few places behind my tail and I ran into it!'](#bitetail) +- [With negative growth the snake drops from the middle of the body](#middleofsnake) +- [It looks like the bug is in the snake](#buginsnake) +- [On the safety of the bug placement loop](#bugplacement) +- [Vertical snake has more space between snake char than horizontal](#verticalsnake) + +# <a name="builtin-test-unit" href="#toc">Built-in test unit for some features!</a> + +Fun fact: There's something of a built-in test unit for some features; much +like some of the other features this was not intentionally designed but is +simply a fun consequence of the features I did implement. + +Let's say you want to verify that the evade mode is at the right count. How +can you verify it without modifying the code? Try: + + SIZE=0 SHED=1 SHEDS=1 EVADE=10 ./prog + +Since you start out at size 0 and you shed every movement then when you're +size 10 (as long as you don't eat a bug of course!) the bug should evade. + +If you set it to `SIZE=10` there would be a difference of 10. Now every +move you will see the size the snake is. But then...Why is it that it +doesn't seem to move until the snake is of size 20? Because you start out at +size 10 of course (but in fact if you observe the snake won't appear to be +of size 20 yet). + +There probably are combinations that can test these types of things I just +don't at this time remember any I might have done. + + +# <a name="stillsnake" href="#toc">The snake doesn't seem to be moving</a> + +One way to show this is in full is to set the initial size and growth size to a +high value; then try each one individually. For example: + + SIZE=100 ./prog + +In this case after you make the first move the snake will keep growing and +so the snake tail stays in the same spot until after it's the 'full size'. +When it has reached the full size then the entire body of the snake will +start to move too (i.e. if the tail isn't moving it is growing or else paused). + +In several tests I set the initial size to a high value, the max to a higher +value still and enabled cannibalism and much of the screen was full of the snake +before it started to move. The [cannibalism.log][] has some examples of both +cannibalism and a long snake that didn't move for most of the game. + +If however you let the snake get to the full size then eat a bug there can +be a moment of lingering where it appears the snake moves for a few places +before it then stops moving and just grows until it's the full size. + +It can also appear to be not moving when the snake is extraordinarily long +and more so when the snake has just eaten: which of course is when it would +grow (just like when shedding). Even so sometimes it takes a moment for the +snake tail to catch up with the body (so to speak) so that it could for a +few moments be difficult to know if where you're going is going to be +occupied or not. + +Basically if the snake head is moving you can consider the snake to be +moving or growing and that's the important point (if you have the default +status line you can also see the coordinates being updated to show this). + + +# <a name="getch" href="#toc">getch() also accepts input from some input hardware other than keyboards</a> + +On my MacBook Pro the trackpad has actually triggered directions; if I were to +swipe up and then down the snake would run into itself. I believe this has to do +with the function call `keypad(v, 1);` which enables arrow keys. + +# <a name="size" href="#toc">SIZE=0 is the same as SIZE=1 and other oddities</a> + +What this means is that for both you will only have the snake head. At this point +you can safely go back on yourself even without cannibalism enabled. This is +intentional; a snake size of 0 is pointless but why should it not be playable +anyway? + +If SIZE < 0 you'll likely win straight away since it's unsigned and it'll wrap +back to the maximum so you will win automatically (this is the same as the +second mode the judges suggested with `SIZE=-1 ./prog`). + +As for the growth sizes (including shedding) if it's < 0: the snake will still +lose its length and display will still be odd: because the snake size is +decreased any element beyond the reduced size isn't touched so the snake +characters will remain on the screen; only the moving snake is what matters. +But it's likely the game will be won fairly quickly because once it's -1 in size +it'll be at the maximum size. + +For example if I say `SIZE=3 GROW=-2` at two bugs the game is won. + +As for growing: anything > 0 it will grow that many; 0 it will not grow (which I +show as a gameplay mode); and < 0 it will 'shrink' as I explained above. You could +say that it's defying physics by growing and shrinking simultaneously but either +way negative size will force a win. + +Here's a fun output: + + < <<<+ + +That's from: + + SHED=1 SHEDS=-1 ./prog + +And right after that you would see: + + YOU WIN! + X:72/156 Y:20/41 S:997/997 B:0 + +Try this though: + + SHEDS=-1 SHED=25 ./prog + +And you'll see that you start to be the normal size but then you leave your +head several places until you end up getting to the max size (by way of it +being unsigned). This isn't a bug even if it might seem like one. In fact +this is the basis of the grow/shrink mode of play that I talk about in the +[gameplay.markdown][] ([gameplay.html][]) file. + +Here's another thing to be aware of. Let's say you do: + + SIZE=1 GROW=-1 ./prog + +How many bugs will it take before you win? In fact it's two: you would see the +head twice: the second time once you 'shrink' down to size 0; it would then be +that if you get another bug you will be at the 'max size': + + YOU WIN! + X:81/156 Y:35/41 S:997/997 B:2 + +# <a name="bitetail" href="#toc">'I was a few places behind my tail and I ran into it!'</a> + +I.e. what happens if you're growing - for example after just eating a bug - and +you're racing towards your tail? If you're behind it should be fine since you're +going the same speed as the snake is, right? Not quite. Because you're growing +you might end up running into your tail (depending on how much you've left to +grow and how far away from your tail)! This happened to me once and it surprised +me and I figured I better note it. + +**Remember: the tail at that point isn't moving yet; the snake is growing!** + + +# <a name="middleofsnake" href="#toc">With negative growth the snake drops from the middle of the body</a> + +For instance it might look like this (the first line is as it happens, the +second pointing to where it happens and the third being what's left after the +rest of the snake has gone through). Doing `SHED=100 SHEDS=-1`: + + ooooooooo>ooo> + ^ + > + +The ^ points to the part that's split from the snake and which will be +there on its own after the snake passes through it. Here's an example with +it being `SHEDS=-3`: + + <ooo<ooooo + ^^^ + <oo + +If you go through the part that has split (which for some might be difficult +to see whilst the snake has not fully left its skin) you won't run into +yourself; if you run into another part though you do. This might be a bit +confusing I know but what kind of animal shrinks in size by leaving its head +behind only to sprout up a new head? Actually...on second thought, I won't +go there! :) + +Anyway it's an odd idea for the snake to shrink by leaving part of its skin: +that's how they grow in the wild so it's a misnomer. The shrinking was only +'discovered' because it's an unsigned number but happily it allows for different +gameplay modes. + +# <a name="buginsnake" href="#toc">It looks like the bug is in the snake</a> + +I show a different example in the [crazy.log][] file but what defines a coordinate +which the snake occupies? If the snake breaks apart then the only part +of the screen the snake is occupying is the place which is actually moving: if +the snake decreases in size by 3 then the three respective characters you can go +through safely. But this also means that a bug can go there! So you might see +something like: + + <*oooooooo + +This is because the snake is no longer there: in fact in this run the snake was +quite a bit lower on the screen and 25 in length. + +# <a name="bugplacement" href="#toc">On the safety of the bug placement loop</a> + +Ilya Kurdyukov shared concern for the loop in the bug placement routine: is it +safe? What he refers to is that it's a potential infinite loop. But is it? I +understand the concern and it's something I played with a lot to be sure that it +doesn't happen. This is how it works. + +To explain it I will go back to the make test program `termcaps` (which is +imperfect for the recommended terminal size but the max snake size is exactly +how it's done in Snake and works well). The minimum terminal size I require in +the game is 10 x 10. This includes the walls and score line. + +Now the default max snake size is 997 but when the terminal is too small it +adjusts the max snake size. For 10 lines and 10 columns you would see: + + $ make test + terminal supports cursor movement + terminal supports making cursor invisible + terminal supports bold + terminal supports colours + + terminal rows 10 (7 playable) + terminal cols 10 (8 playable) + + snake size: 49 (max size: 49) + bugs: 9 (max size: 9) + + at least 28 columns recommended for snake size 49 (is 10) + at least 28 columns recommended for snake size 49 (is 10) + + 1 problem detected (0 fatal). + make: *** [test] Error 1 + +First: what's the problem? It's just a warning that for the snake size of 49 the +recommended size of columns is 28. However this is just for the score text; with +only 10 columns it will overflow and wrap to the next line(s). But if you observe +that 49 is the max snake size. How is this derived and why? + +With 10 rows and columns it's calculated as 7 * 7 (i.e. it's +`(cols-3)*(rows-3)`. However the number of playable locations is in this case 56 +(`playable_rows * playable_columns`). I have played with this many +times and I do not believe there should be a problem. If there is it's from a +very poor implementation of rand() and I discuss this in +[troubleshooting.markdown][] ([troubleshooting.html][]). + +There I also give some test outputs without the cap in place to give an idea of +when it became a problem (or would have). In short this is known but I do not +think it will be a problem and I have given resolutions. In any event without +cannibal mode it's even less likely that you'll ever run into this problem. + +The obvious question is why didn't I put in a break? Because of the IOCCC size +rule 2 and what would it do anyway? I guess it would win but to my mind that is +a bug and I prefer putting in restrictions to try and make it very unlikely. + +# <a name="verticalsnake" href="#toc">Vertical snake has more space between snake char than horizontal snake</a> + +Ilya Kurdyukov also pointed out that depending on orientation of the snake there +are different amount of spaces between the snake char 'o'. This is what he +had to say on it: + +> Yes, it is the problem, space in character terminal is not isotropic +> from a viewer (gamer) perspective so one step up look like two steps +> right. +> +> MATE Terminal 1.20.0, and font "Ubuntu Mono Regular 13" +> +> But, as I said, there is no terminal problem itself, it's because +> character tiles are not square (except for Japanese/Chinese, Japanese +> even have so called full-width English characters in their encoding, +> presented in UTF too). +> +> [https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms][] +> +> So the typical fonts are Half-width or close to it. +> +<img src="halfwidth_vs_fullwidth.png"> + +However the function `mvaddch()` takes a `chtype` which amounts to a C char +with additional information and so the full width Ois too big for the +function call. He reminded me of the old DOS box chars but even if this was +easily duplicable (and it might be and I don't remember) the logic would +have to be changed for drawing the snake and in such a way that would change +the source code layout too much - to say nothing else of the fact I have +also forgotten some of what I did obfuscation wise (and the +[spoilers][] aren't enough here!). + +That being said the font and font size does seem to have somewhat of an +effect on it since his screenshots have wider gaps than mine. + +Once again thank you mate for bringing this to my attention and also playing +with it and providing the resources! Much appreciated! (And although you +suggested it is bugging me I once again here say it's not at all bugging me +but it is very much appreciated and it means a great deal to me. Cheers.) + + +[crazy.log]: crazy.log +[gameplay.markdown]: gameplay.markdown +[troubleshooting.markdown]: troubleshooting.markdown +[troubleshooting.html]: troubleshooting.html +[gameplay.html]: gameplay.html +[cannibalism.log]: cannibalism.log +[https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms]: https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms +[spoilers]: spoilers.markdown +[screenshot of halfwidth vs fullwidth]: halfwidth_vs_fullwidth.png + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/ferguson1/cake.jpg b/ioccc/2020/ferguson1/cake.jpg new file mode 100644 index 0000000000000000000000000000000000000000..badf45ec726485c3d6b553507d9bdc95990efe14 Binary files /dev/null and b/ioccc/2020/ferguson1/cake.jpg differ diff --git a/ioccc/2020/ferguson1/cannibalism.log b/ioccc/2020/ferguson1/cannibalism.log new file mode 100644 index 0000000000000000000000000000000000000000..1ed07d19654464279d0e3fd3c5e2e0eb2c84c5aa --- /dev/null +++ b/ioccc/2020/ferguson1/cannibalism.log @@ -0,0 +1,167 @@ +X:45/89 Y:22/25 S:1675/2001 B:35 +########################################################################################## +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# +# o o o o o oooo o # +# oooooooooo o o o o ooo ooooooooo oooo # +# o ooooooooooooooooooooooooo o o o o o # +# o ooooooooooo ooooooooooooooooooooooo oooooooooooooooo o o o # +#oooooooooooooooooooooooooooooooooooooooooooooooooooooo o o o o o o oo# +# o o ooooooooooooooooooooooooooooooooooooooo o o o*o o oooo o # +# o o o ooooooooooooooooooooooooooooooooooooooo o o o o o o # +# o o o o o ooo o o oo oooooooooooooooooooooooo o # +# o ooooooooooooooooo oooooooo o o oooooooooooo ooooooooooooooooooooooooo o # +# o o o o oooooo o o o o o oooooooooooooooooooooooo o o o o o # +#oooooooooooooooooo o o o o oo o o o o o oo oo o oo o o oooooooooooooooooooo# +# o oooooooooooooooooooooooooooooooooooooooooooooooooooo oo o o oo o o o # +# o o ooooooooooooooooooooooooooooooooooooooooooooooooo o oo o o o # +#oooooooooo oooo o o o o o o o o oo o oooooooooooooooooo ooooooooooooooooo# +# oooooooooooooooo o o o ooooooooo o oo o o o o o o ooooooooooooo # +# ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo o o o o o # +#oooooo o oooooo o o o o o o o ooooooooooooooooooooooooo o ooooooo# +# o o o o o o oooo ooooooooooooooooo o o o o o # +# o o oo o o o ooooo> o oooooooo ooooo o # +#ooooooooo ooooooooooooooooooooo ooooooooooo ooooooo# +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# +########################################################################################## + +X:79/89 Y:9/25 S:1680/2001 B:36 +########################################################################################## +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# +# o o o o o oooo o # +# oooooooooo o o o o ooo ooooooooo oooo # +# o ooooooooooooooooooooooooo o o o o o # +# o ooooooooooo ooooooooooooooooooooooo oooooooooooooooo o o o # +#oooooooooooooooooooooooooooooooooooooooooooooooooooooo o o o o o o oo# +# o o oooooooooooooooooooooooo oo o o ooooooooooooooooooo> o # +# o o o oooooooooooooooooooooooooooooooooooooooooo o o o o o # +# o o o o o o o o o oo o oooooooooooooooooooooooo o # +# o ooooooooooooooooo o o o o oooooooooooo ooooooooooooooooooooooooo o # +# o o o o oooooo o o o o oooooooooooooooooooooooo o o o o o # +#oooooooooooooooooo o o o oo o o o o o ooo oo o oo o o oooooooooooooooooooo# +# o oooooooooooooooooooooooooooooooooooooooooooooooooooo oo *o o oo o o o # +# o o ooooooooooooooooooooooooooooooooooooooooooooooooo o oo o o o # +#oooooooooo oooo o o o o o o o ooo o oooooooooooooooooo ooooooooooooooooo# +# oooooooooooooooo o o ooooooooo o ooo o o o o o o ooooooooooooo # +# ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo o o o o o # +#oooooo o oooooo o o o o o o o ooooooooooooooooooooooooo o ooooooo# +# o o o o o oooo ooooooooooooooooo o o o o o # +# o o o o o oooooo o oooooooo ooooo o # +#ooooooooo ooooooooooooooooooooo ooooooooooo ooooooo# +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# +########################################################################################## + +X:53/89 Y:18/25 S:1690/2001 B:38 +########################################################################################## +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# +# o o o o o oooo o # +# oooooooooo o o o o ooo ooooooooo oooo # +# o ooooooooooooooooooooooooo o o o o o # +# o ooooooooooo ooooooooooooooooo o oooooooooooooooo o o o # +#oooooooooooooooooooooooooooooooooooooooooooooooooooooo o o o o o o oo# +# o * o oooooooooooooooooooooooo o o o oooooooooooooooooooo o # +# o o o oooooooooooooooooooooooooooooooooooooooooo o o o o o o # +# o o o o o o o o o o o oooooooooooooooooooooooo o o # +# o ooooooooooooooooo o o o o oooooooooo o ooooooooooooooooooooooooo o # +# o o o o oooooo o o o o oooooooooooooooooooooooo o o o o o o # +#oooooooooooooooooo o o o oo o o o o o o o o o oo oooooooooooooooooooooooooo# +# o oooooooooooooooooooooooooooooooooooooooooooooooooooo oo oo o oo o o o # +# o o ooooooooooooooooooooooooooooooooooooooooooooooooo o oo o o o # +#oooooooooo oooo o o o o o o o o o o ooooooooooooooooo ooooooooooooooooo# +# oooooooooooooooo o o ooooooooo o o o o <ooooooooooo o ooooooooooooo # +# ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo o o o o o # +#oooooo o oooooo o o o o o o o ooooooooooooooooooooooooo o ooooooo# +# o o o o o oooo ooooooooooooooooo o o o o o # +# o o o o o oooooo o oooooooo ooooo o # +#ooooooooo ooooooooooooooooooooo ooooooooooo ooooooo# +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# +########################################################################################## + +X:61/89 Y:6/25 S:1815/2001 B:63 +########################################################################################## +# oooooooooooooooooooooooooooooooooo # +# o # +# ooooo o ooooooooooo # +# oooooooooo o o * ooooooooooooooooooooo # +#oooooo o oooooooooooooooooooooooooooooooo <ooooooooooooooooooooooooooo# +# o ooooooooooooooooooooooo o oooo o o o o ooo # +# o o oooo oooooooooooooooooooooooooooooooo o ooooooooooooooooooo ooo # +# o ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo ooo # +# o o o o oooooooooooooooooooooooooooooooooooooooooooooo o o o o ooo # +# o oooooooooooooooooooooooooooooooooooooooooooo o oooooooooooooooooooooooooooooooo # +#ooooooooooooooooooooooo o oooooooooo o ooooooooooooooooooooooooooooooo# +# o o o o oooooo o ooooooooooooooooooooooooooooooooooooooooooo # +#oooooooooooooooooo o o o oo o o o ooooo o o oooooooooooooooooooooooooo# +# o oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo o oo oo # +# o o oooooooooooooooooooooooooooooooooooooooooooooooooo oo o ooooooooooo # +#oooooooooo oooo oooooooooooooo o o ooooooooooooooooo ooooooooooooooooo# +# oooooooooooooooo oo ooooooooo o oooooooooooooo o ooooooooooooooooo # +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooo o oooooooooooooo# +#oooooo ooooooooooooooooooooooooooooooooooooooooo o ooo ooooooo# +# oo o oooo oooo o o oooooo o # +# ooooooooooooooooo ooooooooooooooooooo oooooooooooooooooooo o # +#ooooooooo ooooooooooooooooooooooooooooooooooooooooooooo ooooooo# +# # +########################################################################################## + + +X:47/89 Y:5/25 S:1815/2001 B:63 +########################################################################################## +# ooooooooooooooooo # +# o # +# ooooo o ooooooooooo oooo # +# oooooooooo o o *<ooo o ooooooooooooooooooooo # +#oooooo o oooooooooooooooooooooooooooooooo oooooooooooooooooooooooooooooooooooo# +# o ooooooooooooooooooooooo o oooo o o o o ooo # +# o o oooo oooooooooooooooooooooooooooooooo o ooooooooooooooooooo ooo # +# o ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo ooo # +# o o o o oooooooooooooooooooooooooooooooooooooooooooooo o o o o ooo # +# o oooooooooooooooooooooooooooooooooooooooooooo o oooooooooooooooooooooooooooooooo # +#ooooooooooooooooooooooo o oooooooooo o ooooooooooooooooooooooooooooooo# +# o o o o oooooo o ooooooooooooooooooooooooooooooooooooooooooo # +#oooooooooooooooooo o o o oo o o o ooooo o o oooooooooooooooooooooooooo# +# o oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo o oo oo # +# o o oooooooooooooooooooooooooooooooooooooooooooooooooo oo o ooooooooooo # +#oooooooooo oooo oooooooooooooo o o ooooooooooooooooo ooooooooooooooooo# +# oooooooooooooooo oo ooooooooo o oooooooooooooo o ooooooooooooooooo # +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooo o oooooooooooooo# +#oooooo ooooooooooooooooooooooooooooooooooooooooo o ooo ooooooo# +# oo o oooo oooo o o oooooo o # +# ooooooooooooooooo ooooooooooooooooooo oooooooooooooooooooo o # +#ooooooooo ooooooooooooooooooooooooooooooooooooooooooooo ooooooo# +# # +########################################################################################## + +Another example invocation where the snake head is in the snake and where the snake +hadn't yet moved: + + CANNIBAL=1 SIZE=1500 GROW=2 MAXSIZE=1600 ./prog + +X:55/89 Y:11/25 S:1564/1600 B:32 +########################################################################################## +# oooo ooooooooooooooooooooooooo o # +# o ooooooooooooooooooooooooooooooooooooooooooooo ooooooooooooooooo # +#ooo o o o o o oooooo# +# o o o oooooooooooooooooooooooooo o # +#oooooooooooooooooooooooooo o ooo o oo oooooooooooooooooooooo# +#oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# +# o o ooooooooooooo oooooooooooooooooooooo ooo oo o o o oo# +#ooo o o oooooo o oooo ooo oo o o oooo# +# o o o oooo o o oo ooo oooooooooooooooooo oo# +# o o o ooooooooooooo oooooooooooooooo ooooo<oooooooooooooooooooooooooooooo # +# o o o o ooooooooo oooooooooooooooooooooooooooo o o o o # +# o ooooooo o o o oooooooooooooo o o o o o o ooooo # +# o o o o o o o o o o o o o # +# o o o o o o o* ooooooooooooooooooo o o ooo # +# o o o o o oooooooooooooooooooooooooooooooooooooooooooo o o # +# oooooooooooooo o o oo o o oooooooooooooooooooooooooooooooooooooo # +# o oo o o oo oooooooooooooo o o o oooooooooooo # +#oooooo oo oooooooooooooo o o o o o o ooo oooooo# +# ooooo o o o o oooooooooooooooooooooooooooooooo o # +# o oooooooooooooo o o o o ooooooooo o o # +# o o oooooo o oooooooooooo o o # +# oooooooooooooooooooooooooooooooooooooooooooooooooooo ooo o # +# ooooooooooo ooooooooooooo o oooooooooo # +########################################################################################## diff --git a/ioccc/2020/ferguson1/chocolate-cake.text b/ioccc/2020/ferguson1/chocolate-cake.text new file mode 100644 index 0000000000000000000000000000000000000000..feff7f3ec5a48cd45720731b525a651de8826070 --- /dev/null +++ b/ioccc/2020/ferguson1/chocolate-cake.text @@ -0,0 +1,189 @@ +# Double-layered Chocolate Fudge Cake + +Here's a delicious double-layered chocolate fudge cake ([picture][]) that is +something of my mum's speciality. It's complicated and I should warn that nobody +has seemed to get it down as well as she has but it's well worth the effort if +you love chocolate. My late stepmum who only liked white chocolate loved this +cake! + +There are two sets of ingredients and instructions; the cake and the icing. In +addition there are some notes to pay attention to; some will be repeated because +they're really important for the quality of the cake. + +Below I have included the ingredients separately but I include them within the +instructions as well and in bold. Also in bold are some of the special notes. + +Finally note that depending on where you are in the world this might not work in +the warmer months of the year for the icing in particular. Oh and here's an +amusing fact about the [IOCCC and chocolate][]. Did I say 'the IOCCC'? I actually +meant **'an IOCCC'**: it stands also for **'International Office of Cocoa, Chocolate +and Sugar Confectionery'**. Perfect. + +See also the [International Original Chocolate Cake Contest tweet][] from +[fellow IOCCC winner Ilya Kurdyukov][] ([GitHub][]) as well as the +[IOCCC cake source image][] of the picture in the tweet (which he painted over +my photo of the cake with GIMP). + + +## Measurements + +This was originally from an American cookery book so the measurements are in the +US standards. A nice resource (that has much more than just cooking) is +[http://www.onlineconversion.com/cooking.htm][]. This will particularly matter +for cups, teaspoons, tablespoons and ounces. + +For example a US cup is not the same as Canadian cup and a metric cup differs +too. There's also a difference for teaspoons and tablespoons: there are metric, +UK and US teaspoons and tablespoons. There's both a UK and US ounce also. + +## Baker's chocolate + +Baker's chocolate is a brand name and the product in question is unsweetened +chocolate bars used for baking. According to a [chocolates FAQ][] it might be +called different things: + + Bitter chocolate contains no sugar and is often called 'unsweetened' or + 'baking' chocolate. In some countries it's called 100% cacao since it's + composed only of ground up cocoa beans, and nothing else. + +The FAQ suggests that you might have to look for a baking supply shop but I +cannot offer any specific advice other than it's unsweetened chocolate bars for +baking. The FAQ talks about what looks like substitutes but I have no idea what +that would turn out as; I somehow suspect it wouldn't be good. + +Either way please **still pay attention to the notes on the chocolate in the recipe and +recipe notes because they're really important!** + +## Special notes for the cake + +**PAY CLOSE ATTENTION TO THESE:** + +* **USE MARGARINE**. Butter does not work well. + +* Over the years they changed the size of the unsweetened chocolate squares; + they used to be one ounce each now they are 1/4 ounce each square so be sure to + note the amount is by ounce not squares as listed. See the measurements link + if there's any doubt. + +* Pay careful attention to **cook for only the indicated time**. + +* **Remove the cake from the pans 2 minutes after removing from oven**. Then allow + to fully cool on racks. The important point is that they don't overcook. + +* When the recipe was first written they sold powdered sugar in a box; now + it's confectioners sugar in a bag. My mum experimented with the amount and + found that 4 cups seems about right. + +* She uses **whole milk** for this recipe; she doesn't know if it really matters + but given that she and I both prefer skim milk except for here and in + chocolate milk I would recommend whole milk for this recipe too. In any case + it turns out great! + + +## Cake Ingredients + +* 3 oz unsweetened (Baker's) chocolate +* 2 and 1/4 cups flour +* 2 tbsp baking soda +* 1/2 tsp salt +* 2 and 1/4 cups packed brown sugar +* 3 eggs +* 1 and 1/2 tsp vanilla +* 1/2 cups margarine +* 1 cup (boiling) water +* 1 cup sour cream + + +## Cake Preparation + +1. Lightly grease two 9 x 1.5 inch round pans; lightly dust with flour. + +2. Preheat oven to 350 F (176.67 C). + + +## Cake Directions + +1. Melt **3 oz unsweetened chocolate** in double boiler or small bowl over + **hot (*but not boiling*) water**; let cool whilst proceeding. + +2. Sift **2 1/4 cups flour**, **2 tsp baking soda**, and **1/2 tsp salt** + +3. Beat **1 stick margarine** in large bowl *until soft*. + +4. Add **2 1/4 cups packed brown sugar** and **3 eggs**. Beat until light and + fluffy. + +5. Beat in **1 1/2 tsp vanilla** and **cooled melted chocolate**. + +6. Stir in dry ingredients alternately with **1 cup sour cream**; always beat + until smooth. + +7. Stir in **1 cup boiling water**. + +8. Pour into prepared pans. + +9. Bake for **ONLY 35 minutes** (NO LONGER) at 350 F (176.67 C). + +10. When you take the cake out put the cake pans on a cooling rack for **TWO + MINUTES ONLY AND THEN IMMEDIATELY TURN CAKES OUT ON TO RACK**. Let cool + completely. + + +## Icing Ingredients + +* 4 oz unsweetened chocolate (Baker's chocolate) +* 1/2 cup margarine +* 4 cups powdered sugar +* 1/2 cup whole milk +* 2 tsp vanilla + +You will also need a bigger pan or bowl that can have ice water that the icing +bowl can sit in. + +## Special notes for the icing + +**PAY CLOSE ATTENTION TO THESE:** + +* Make sure that the melted chocolate and margarine does not get solid. + +* For step #4 put **8 to 10 ice cubes** in a pan or big bowl (that's big + enough that another bowl can fit in it). Add an inch of water and then set + the bowl with the icing in the pan or bowl of ice water. **Do not let the + icing get wet!** + +* Do not let icing get too thick. + +* Use **whole milk.** + + +## Icing Directions + + +1. Combine **4 oz unsweetened chocolate** and **1/2 cup margarine** in pan. + Melt and remove from heat. **DO NOT LET IT GET SOLID.** + +2. Combine **3 1/4 cups powdered sugar**, **1/2 cups whole milk** and **2 tsp + vanilla** into a bowl. **Stir until smooth**. + +3. Add chocolate mixture. + +4. Set bowl in pan/bowl of ice and water. Beat with spoon/mixer until it's + thick BUT not too thick. Make sure icing doesn't get wet! The idea is to + **MAKE THE BOWL IT'S IN COLD *but not let the icing get wet***. + +[picture]: cake.jpg +[http://www.onlineconversion.com/cooking.htm]: http://www.onlineconversion.com/cooking.htm +[IOCCC and chocolate]: http://www.gomc.com/firstpage/200103068.pdf +[International Original Chocolate Cake Contest tweet]: https://twitter.com/ilyakurdyukov/status/1290520266087571458?s=20 +[fellow IOCCC winner Ilya Kurdyukov]: https://twitter.com/ilyakurdyukov +[GitHub]: https://github.com/ilyakurdyukov +[IOCCC cake source image]: ioccc-cake.jpg +[chocolates FAQ]: https://www.davidlebovitz.com/chocolate-faqs/ + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/ferguson1/compile_commands.json b/ioccc/2020/ferguson1/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..2f9c6ad5d318b88e2f0807f07c956de9855ba59f --- /dev/null +++ b/ioccc/2020/ferguson1/compile_commands.json @@ -0,0 +1,97 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-Wno-unused-value", + "-Wno-misleading-indentation", + "-Wno-parentheses", + "-Wno-unknown-warning-option", + "-D_XOPEN_SOURCE", + "-D_POSIX_C_SOURCE", + "-Df(a,b)=((a)<(b)?(a):(b))", + "-DWALL=COLOR_CYAN", + "-DHEAD=COLOR_RED", + "-DBODY=COLOR_GREEN", + "-DWB=COLOR_BLACK", + "-DHB=COLOR_BLACK", + "-DBS=COLOR_BLACK", + "-DBG=COLOR_WHITE", + "-DBB=COLOR_BLACK", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + }, + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-Wno-unused-value", + "-Wno-misleading-indentation", + "-Wno-parentheses", + "-Wno-unknown-warning-option", + "-D_XOPEN_SOURCE", + "-D_POSIX_C_SOURCE", + "-Df(a,b)=((a)<(b)?(a):(b))", + "-DWALL=COLOR_CYAN", + "-DHEAD=COLOR_RED", + "-DBODY=COLOR_GREEN", + "-DWB=COLOR_BLACK", + "-DHB=COLOR_BLACK", + "-DBS=COLOR_BLACK", + "-DBG=COLOR_WHITE", + "-DBB=COLOR_BLACK", + "-O3", + "-Wno-padded", + "-Wno-incompatible-pointer-types-discards-qualifiers", + "-o", + "termcaps", + "termcaps.c" + ], + "directory": ".", + "file": "termcaps.c" + }, + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-Wno-unused-value", + "-Wno-misleading-indentation", + "-Wno-parentheses", + "-Wno-unknown-warning-option", + "-D_XOPEN_SOURCE", + "-D_POSIX_C_SOURCE", + "-Df(a,b)=((a)<(b)?(a):(b))", + "-DWALL=COLOR_CYAN", + "-DHEAD=COLOR_RED", + "-DBODY=COLOR_GREEN", + "-DWB=COLOR_BLACK", + "-DHB=COLOR_BLACK", + "-DBS=COLOR_BLACK", + "-DBG=COLOR_WHITE", + "-DBB=COLOR_BLACK", + "-O3", + "-o", + "prog.alt", + "prog.alt.c" + ], + "directory": ".", + "file": "prog.alt.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/ferguson1/crazy.log b/ioccc/2020/ferguson1/crazy.log new file mode 100644 index 0000000000000000000000000000000000000000..d23e9641833943c302a63964778052ef11013a96 --- /dev/null +++ b/ioccc/2020/ferguson1/crazy.log @@ -0,0 +1,106 @@ +The following are a few screen dumps of: + + SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog + +As you will see it took 17 bugs to get down to below 0. Notice how I had to get +down to 0 more than once: because I moved enough times before I got the last +bug that I grew by 5 in size. I then however moved a bit more and ate a bug +which brought me down to -5 therefore winning at the max size of 250. This then +showed: + + YOU WIN! + X:62/89 Y:5/25 S:250/250 B:17 + +Observe all the arrows on the screen; that's where a bug was that I ate and +then I split off losing 10 in size. The first one dump I got myself already to 15: + +X:17/89 Y:15/25 S:15/250 B:13 +########################################################################################## +# <ooooooooo o <ooooooooo* # +# o o> # +# o ooo oooo # +# o o ooooooooo> o v # +# o o oo o # +# o o o o # +# o o o o # +# <oo o o o # +# o # +# o o # +# o o # +# o o o # +# <ooo o oooooooo> # +# <oooooooooooooo o o # +# o o # +# o o # +# < ooo o o # +# o o # +# o v # +# oooooo> # +# o # +# o o> # +# oooooo # +########################################################################################## + +But here now I'm at 0; the head is the sole left arrows: + +X:19/89 Y:12/25 S:0/250 B:16 +########################################################################################## +# <ooooooooo o <oooooooo <ooooooo # +# o o> oo # +# o ooo oooo # +# o o oooooo*oo> v # +# o o oo o oo> # +# o o o o oo # +# o o o oooo # +# <oo o o o # +# o # +# o o # +# < o o # +# o o o # +# <ooo o oo ooooo> # +# o o # +# o o # +# o o # +# < ooo o # +# o o # +# <oooooooo o v # +# oooooo> # +# o # +# o o> # +# oooooo # +########################################################################################## + +I ended up moving enough times where my size went back up to 5; the head of the +snake is in this file line 80 col 56; the bug is at line 81 col 63: + +X:55/89 Y:4/25 S:5/250 B:16 +########################################################################################## +# <ooooooooo o <oooooooo <ooooooo # +# o o> oo # +# oooo> oooo # +# o o oooooo*oo> v # +# o o oo o oo> # +# o o o o oo # +# o o o oooo # +# <oo o o o # +# o # +# o o # +# o o # +# o o o # +# <ooo o oo ooooo> # +# o o # +# o o # +# o o # +# < ooo o # +# o o # +# <oooooooo o v # +# oooooo> # +# o # +# o o> # +# oooooo # +########################################################################################## + +But did you see anything strange? The bug is on the fourth line below the upper wall. +However it appears to be inside the body of the snake! But actually that's just where +the snake split off at some point: the snake no longer occupies that place and indeed I +could safely go through that part of the screen. diff --git a/ioccc/2020/ferguson1/gameplay.text b/ioccc/2020/ferguson1/gameplay.text new file mode 100644 index 0000000000000000000000000000000000000000..22a0c3caf36233f27500823f01658c8c4338d28f --- /dev/null +++ b/ioccc/2020/ferguson1/gameplay.text @@ -0,0 +1,794 @@ +Playing the game is very simple but because there are many different modes I +have included much more than just the input keys and a few printouts of the +game. For normal play you probably don't even need this file at all unless it be +for the input keys. + +<a name="toc"></a> +1. [Testing terminal environment/capabilities](#support) +2. [Input keys](#input) +3. [Gameplay](#gameplay) + * [The initial screen](#initial) + * [Playing the game](#playing) + * [Walls](#walls) + * [Cannibalism](#cannibalism) + * [Stretching (shedding)](#shedding) + * [Winning](#winning) + * [Quitting](#quitting) +4. [Gameplay modes](#modes) + * [**Photosensitive epilepsy/Stimulation overload trigger warnings**](#warning) + * [Drawing / Practice mode](#drawing) + * [Computer playing / Automatic mode (**Photosensitive epilepsy/Stimulation overload trigger**)](#auto) + * [Variations](#auto-variations) + * [Grow-Shrink (Positive/Negative Winning) mode](#grow-shrink) + * [Hypnotic / Sleepy mode (**Photosensitive epilepsy/Stimulation overload trigger**)](#hypnotic) + * [Stimulation / Calming mode](#stim) + * [Other ideas](#other-ideas) +5. [Scripts](#scripts) + * [Colours selection](#colours) + * [Automate the above gameplay modes](#preset) +6. [Game variables](#variables) + * [WAIT - Snake speed](#wait) + * [EVADE - Bug evasion frequency](#evade) + * [SIZE / MAXSIZE - Initial snake / max sizes](#sizes) + * [GROW / SHEDS - Growth / Shedding sizes](#growth) +7. [Conclusion (and inspirational words for everyone)](#conclusions) + +# 1. <a name="support" href="#toc">Testing terminal environment/capabilities</a> + +Most people probably won't have any issue at all but for those who have any +problems with the terminal see the [terminals.markdown][] file for more +information on the terminal capabilities testing utility I include. + +For troubleshooting other problems see [troubleshooting.markdown][] +([troubleshooting.html][]) and [bugs.markdown][] ([bugs.html][]). + + +# 2. <a name="input" href="#toc">Input keys</a> + +- Left, right, up and down **arrow keys**: Move that direction. + +- 'q' (and 'Q'): Quit the game. + +- Space (`' '`): Pause/resume the game (direction keys will also resume). + Note that no other keys will resume the game; however if you press a key + that `getch()` picks up on and the game is not paused then it will be as if + you pressed the current direction key (assuming you already moved the snake). + +# 3. <a name="gameplay" href="#toc">Gameplay</a> + +Here I will show the initial screen as well as what a few things look like. If +you don't feel you need this but you want to configure colours jump to [colour +selection](#colours). You can also jump to [gameplay modes](#modes) or [game +variables](#variables). + +The bug colour by default is white; the snake head colour is red and the snake +body colour is green. The walls are cyan. + + +## <a name="initial" href="#toc">Gameplay: The initial screen</a> + +When you load the game you will see a screen that looks something like the +below. Note that the top line is the score/status line: the top wall is at line +1 and the left wall is column 0. Below I use the coordinates in the X/Y order +(ncurses is the opposite: Y/X). I will parenthesise the numbers below to refer +to the number in the diagram: + + X:24/49 Y:8/16 S:5/658 B:0 + ################################################## + # # + # # + # # + # # + # # + # # + # + # + # # + # * # + # # + # # + # # + # # + # # + ################################################## + + +- The snake (`+`) is at (24),(8). The bug char is `*` and the wall char is + `#`. When the snake moves the head will be an arrow facing the direction it + is moving; the body is 'o'. + +- The top wall is always line (1), the left wall is always column (0), the + bottom wall is line (16) and the right wall is column (49). If walls are + impassable and you run into any of these the game is over (you can slither + at the edge of the wall); else you'll come out the opposite side. + +- The snake size is (5): but until you start to move it's technically 1 (even + if you set **SIZE=0** this applies). This is so that you can decide which + direction from the centre of the screen. By default the head colour is red; + the body is green. The snake will grow by one until it reaches the right + size. + +- The maximum snake size is (997): this is the default; it can be changed but + it will always have an upper limit depending on the terminal size. + +- The number of bugs eaten so far is 0. + + +## <a name="playing" href="#toc">Gameplay: Playing the game</a> + + + X:39/49 Y:8/16 S:5/658 B:0 + ################################################## + # # + # # + # # + # # + # # + # # + # oooo> # + # # + # * # + # # + # # + # # + # # + # # + ################################################## + +I let the snake grow to its full size (with the head at (39),(8)) and I'm two +places above the bug so let's go down: + + X:39/49 Y:9/16 S:5/658 B:0 + ################################################## + # # + # # + # # + # # + # # + # # + # oooo # + # v # + # * # + # # + # # + # # + # # + # # + ################################################## + + +Now you see that the snake is going down and in one move the bug will be eaten. +Let's do that: + + X:36/49 Y:10/16 S:10/658 B:1 + ################################################## + # # + # # + # # + # * # + # # + # # + # # + # # + # ^ o # + # oooo # + # # + # # + # # + # # + ################################################## + +Observe that the bug was eaten and a new bug spawned elsewhere. I went left +three and then up one and could slither on to the bug. + + +# <a name="walls" href="#toc">Gameplay: Walls</a> + +By default walls are passable (**WALLS=1**). Let's get to full size and go +through the top wall: + + + X:36/49 Y:15/16 S:10/658 B:1 + ################################################## + # o # + # o # + # o # + # * o # + # o # + # o # + # o # + # o # + # o # + # # + # # + # # + # # + # ^ # + ################################################## + +There you can see I have grown to the full size and went through the top wall; +the head is now at the opposite wall. Continuing: + + X:36/49 Y:11/16 S:10/658 B:1 + ################################################## + # o # + # o # + # o # + # * o # + # o # + # # + # # + # # + # # + # ^ # + # o # + # o # + # o # + # o # + ################################################## + +I might then have turned to the left and then shortly go up to get the bug. This +goes on until you lose, quit or win the game. + + +When you specify **WALLS=0** the walls become an obstacle that end the game. It +might look like (I set the starting size to 150 and had only just started): + + + X:20/49 Y:2/16 S:150/658 B:0 + ################################################## + # ^ # + # o # + # o * # + # o # + # o # + # o # + # ooooo # + # # + # # + # # + # # + # # + # # + # # + ################################################## + +If I continue going up I will see: + + OUCH! + X:20/49 Y:1/16 S:150/658 B:0 + + + + +# <a name="cannibalism" href="#toc">Gameplay: Cannibalism</a> + +By default cannibalism is disabled (**CANNIBAL=0**) so if you run into yourself it might look +something like: + + X:45/49 Y:10/16 S:10/658 B:1 + ################################################## + # # + # # + # # + # * # + # # + # # + # # + # ooooo # + # ^ o # + # ooo # + # # + # # + # # + # # + ################################################## + +If I were to do any movement but turn to the left I would run into myself. I'll +go to the right two spaces: + + OW! + X:47/49 Y:10/16 S:10/658 B:1 + + +But **CANNIBAL=1** can look very funny both in movement and still especially +when you go through yourself several times when the snake is rather long. For +example going through walls and the snake a few times: + + X:4/49 Y:12/16 S:165/658 B:3 + ################################################## + #oo o ooooo o o o# + # oooo o ooo o# + # ooooooooooooooooooo# + # o # + # oooooooooo o # + # o o o # + # o oooo o o # + # o o o o # + # ooooooooooooooo # + # o o* # + # oo> o o # + # o oooooooo o # + #oooooooooooooo o oooo oooooooo# + # o o o o o # + ################################################## + +I'll go back through myself now: + + X:6/49 Y:14/16 S:165/658 B:3 + ################################################## + #oo o ooooo o o o# + # oooo o ooo o# + # ooooooooooooooooooo# + # o # + # oooooooooo o # + # o o o # + # o oooo o o # + # o o o o # + # ooooooooooooooo # + # o o* # + # ooo o o # + # oo oooooooo o # + #ooooo>oooooooo o oooo oooooooo# + # o o o o o # + ################################################## + +If you note that the head is at (6),(14) I will go one more to the right and you +will see that the arrow has moved over: + + X:7/49 Y:14/16 S:165/658 B:3 + ################################################## + #oo o ooooo o o o# + # oooo o ooo o# + # ooooooooooooooooooo# + # o # + # oooooooooo o # + # o o o # + # o oooo o o # + # o o o o # + # ooooooooooooooo # + # o o* # + # ooo o o # + # oo oooooooo o # + #oooooo>ooooooo o oooo oooooooo# + # o o o o o # + ################################################## + +Try this: Get a reasonable length and then go back on yourself (if you're going +left go right etc.) and then after some length (but before you get beyond the +snake) turn (so that you go perpendicular) and then watch as the snake starts +unwinding at one place and then suddenly unwinds another direction. + +An example of extreme cannibalism is in the [cannibalism.log][] file. It has +more than one run the first of one has several dumps. I didn't move for a long +time: the initial size was 1500 and I would have won before moving if I went +after bugs right away. In the last two captures of the first invocation (the +third and second to last dump) the bug, head and tail of the snake are at: + + Bug: line 87, col 47 + Head: line 88, col 62; and line 115, col 48 + Tail: line 84, col 46; and line 112, col 29 + +The final example has the snake inside itself. + +# <a name="shedding" href="#toc">Gameplay: Shedding (stretching)</a> + +This feature will make you grow by the value of **SHEDS** for every **SHED** +movements (the counter isn't incremented when you eat a bug). Basically growing +without eating a bug (stretching would be better name here). + + +# <a name="winning" href="#toc">Gameplay: Winning</a> + +If you ever get to the **MAXSIZE** the game is won. You can force a win by +setting the max size to a smaller value than the size you specify (or the +default) or setting the size to higher than the default (or < 0 which will end +up being > the max size though I suppose there might be some value that makes it +less than again - I'm not going to try and figure that out however). Anyway: + + SIZE=-1 ./prog + YOU WIN! + X:24/49 Y:8/16 S:658/658 B:0 + +Observe that the size isn't the default 997: because the screen size is too +small for that value (see [terminals.markdown][]). + +The reason I chose 997 is that it leaves a bit of a challenge for some (maybe +most) people but it's still winnable. Previously even I couldn't have won unless +maybe a much bigger screen, if both cheat modes were disabled. I probably could +win without any cheat mode enabled on my 24" monitor but I probably would need +at least one cheat mode on my 13" laptop (I don't need both enabled). + +The beauty though is the game can be winnable by anyone since you can define the +max size to win. Games are meant to be fun: who enjoys games that can never be +won? Very few probably do and those who do enjoy them it probably are games that +are relaxing and stimulating (which admittedly this game can be - but still I +want it to be winnable too). + +Another reason I chose 997: it's prime and the judges love prime numbers. +Actually, this is the main reason for the number: I had changed it down to 1000 +but then it occurred to me that there are prime numbers close to 1000 so why not +choose one instead (that was less than 1000)? And so I did. Another fun fact: at +the default starting size and growth size of 5 the number of bugs needed before +the game is won is 199 - also a prime! + + +# <a name="quitting" href="#toc">Gameplay: Quitting</a> + +If you wish to quit you can hit 'q' (case-insensitive). For example: + + X:24/49 Y:8/16 S:5/658 B:0 + + + +# 4. <a name="modes" href="#toc">Gameplay modes</a> + +Here I list a number of different modes of play. In the [bugs.markdown][] +([bugs.html][]) file I even show how there's a built-in test unit for some +modes! There are certainly other modes that could be imagined: the modes below +happened over time and some were simply an accidental discovery or something I +thought of by a chance; others were thought out from the beginning but were +improved over time. + +The [play.sh][] script sets up some of these automatically; I describe it after +the modes below. + + +## <a name="warning" href="#toc">Photosensitive epilepsy/Stimulation overload trigger warnings</a> + +If you have **photosensitive epilepsy please be careful** especially with low values +for both **WAIT** and **EVADE**. It appears that the [number of hertz (flashes) +per second triggering seizures][] is wide but depending on the variables it +easily can be in the range. + +There are different patterns and lights flashing at different speeds so please +exercise caution. This could trigger seizures and **it might also be too much +stimulation for some people.** + +**Please be careful of these if these types of things have ever affected you or if +you have any form of epilepsy. Thank you.** + +## <a name="drawing" href="#toc">Gameplay mode: Drawing / Practice mode</a> + +If you want to draw the snake wherever you like on the screen you can do this by +modifying the wait time (for input) to -1 (or any value < 0): then the snake +does not move until you press a movement key. For example: + + WAIT=-1 ./prog + + +When you eat a bug the snake will grow and you can draw more. If you want to +make it so you can go through yourself: + + WAIT=-1 CANNIBAL=1 ./prog + +If you don't want to start out so small (i.e. you want to be able to draw more +quickly) you can just set the size to a bigger number (and you could do the same +with growth and moult/shed): + + SIZE=50 CANNIBAL=1 WAIT=-1 ./prog + +Do note that although you're a bigger size you still grow one movement at a +time. + +Okay but then if you get too many bugs the drawing will be over. If this proves +to be a problem simply do: + + SIZE=100 CANNIBAL=1 WAIT=-1 GROW=0 ./prog + +Or something like that (maybe make the size bigger but that's up to you). You +could also set the max size to be the highest possible by saying + + MAXSIZE=-1 + +Which I've done in the [play.sh][] script. + +I discuss how this mode works in [spoilers.markdown][]. + +Here's an example run where I spelt 'SNAKE'. As you can see it's far from +perfect: the snake after all does not leave gaps and the game does not support +diagonal movement and I also made a mistake and had to modify what I was aiming +for. But you can consider this mode drawing or practice mode. + + oooooooooo ooooo o oo ooooo + o o oo o oo o ooo o + oooo o oo ooooooo oooo ooooo + o o ooo oo o ooo o + oooo o oo ooo oooooooo> + + +## <a name="auto" href="#toc">Gameplay mode: Computer playing / Automatic mode (Photosensitive epilepsy/Stimulation overload trigger)</a> + +**Photosensitive epilepsy/stimulation overload trigger warning:** +For those who have epilepsy or are susceptible to stimulation overload from +flashing lights please do be careful with this mode. Depending on your +susceptibility this could very well trigger seizures or other discomforts and I +wouldn't want that to happen to anyone. This mode has a lot of flashing of +different colours and depending on the exact parameters you specify it could +easily be in the trigger range for epilepsy but potentially stimulation overload +too. + +If you're still here you can create this effect like: + + WAIT=0 WALLS=1 CANNIBAL=1 ./prog + +As long as the bug evades you'll find that the snake is growing because it's +actually eating bugs; the computer is actually playing the game by itself! You +can still move the snake though it won't seem like you have much control over +it. If you pause the game you can see that it's bigger (you probably will be +able to even without pausing it). + +Basically the snake is moving so fast that because the bug evades the bug will +inevitably move in the snake path's and therefore be eaten. + +You might find it goes quicker if you set the evade count to a lower value for +example 1. Or you might not. But as long as the bug moves the computer can play +by itself. + +Quick tests suggest that bigger dimensions it gets bigger quicker. But it also +seems to take longer for it to get a bug as it gets longer. I believe these +happen because the bug has to find a X and Y coordinate that's not occupied and +so with fewer available it has a harder time finding a place in that one line. + +### <a name="auto-variations" href="#toc">Computer player variations</a> + +Here's how to make the bug move every time the snake moves: + + CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 ./prog + + +#### Help the computer win fairly quickly + +If you want to see the game 'win' try something like: + + CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 MAXSIZE=10 ./prog + + +#### Negative growth (Shrink) Automatic mode + +Here's a fun one I just thought of (a long time after these other modes were +thought of): + + WAIT=0 EVADE=1 GROW=-1 SIZE=9 MAXSIZE=10 CANNIBAL=1 ./prog + +What you'll see is that first the snake will get to the size of 9 - whether it +shows to be 10 characters depends on whether or not it gets a bug before it can +get to that length - and then it'll start shrinking until it's just the head +then the head again (i.e. 1 then 0 in size) and then win! This is also in the +[play.sh][] script. + + +#### Adjusting the time/speed + +Of course you can also do something like: + + WAIT=5 WALLS=1 CANNIBAL=1 ./prog + +Which although might not seem like it is significantly slower. + +#### Moving the snake about to create patterns + +If you press different direction keys in some pattern you will see a pattern +form too (entirely dependent on how fast you react, what keys you press and I +suppose also how much the bug moves and the chance of being eaten also). + +#### Other ideas + +Here's an idea: how many moves is needed to make it possible to have some sort +of success in catching bugs? Obviously the dimensions will affect this value. + +How long will it take for the snake to run into itself? For instance by doing: + + WAIT=0 ./prog + +On my 13" MacBook Pro at the default settings going horizontally the snake ran +into itself at: + + OW! + X:57/156 Y:20/41 S:155/997 B:30 + +What if you set the size to a high value? The lowest? There are bound to be +other games to play with this feature! + +## <a name="grow-shrink" href="#toc">Gameplay mode: Grow-Shrink mode (Positive and Negative Winning)</a> + +In this mode you're simultaneously growing and shrinking but because the max +size is unsigned you can win both by shrinking to the point of losing your body +or growing to the full size directly. This is how it works: + +You have a negative shedding growth and a positive growth size: negative and +positive winning. Depending on the parameters specified it might go one way over +the other. Try: + + SIZE=150 SHEDS=-5 GROW=10 SHED=50 MAXSIZE=250 ./prog + +What this does is set the size to 150 (to make it not go down so quickly) and +then for each bug you eat it adds 5 to the size; for every 50 moves (that you +don't get the bug) you shrink by 5. You will find that at times you might only +decrease in size but then at other times - depending on size of screen and how +lucky you are with where the bug is relative to where it last was - you might be +growing. Combining this with the drawing mode could be interesting but I never +actually tried it. + +The parameters above were chosen after playing with the mode a bit to find a +value that wouldn't take that much time but still would pose a challenge. One +could reverse it so that one shrinks more than growing. + +The [crazy.log][] file has several screen dumps with this idea. + +You could also have it so that eating a bug makes you shrink and moving so many +moves you grow. I tried this and for me it was far more fun. The [play.sh][] +also has this mode: + + SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog + +Obviously there are many other variations. The [play.sh][] script has some +of them (the above is option 5; others are 4, 15 and 16 but only options 4 and 5 +are called Grow / Shrink). + + +## <a name="hypnotic" href="#toc">Hypnotic / Sleepy mode (**Photosensitive epilepsy/Stimulation overload trigger**)</a> + +**Photosensitive epilepsy/stimulation overload trigger warning:** +For those who have epilepsy or are susceptible to stimulation overload from +flashing lights and patterns please do be careful with this mode. Depending on your +susceptibility this could very well trigger seizures or other discomforts and I +wouldn't want that to happen to anyone. The default wait time is 231ms, the +typical range of seizures is 3 to 30 flashes per seconds (but can be higher) and +that means that at **EVADE=1** every 231ms there will be a flash in addition to the +snake moving too. + +Anyway this might sound absurd but it can be somewhat hypnotic by doing: + + EVADE=1 CANNIBAL=1 ./prog + +And just moving the snake about not trying to catch any bugs - just let whatever +happens happen. + + +## <a name="stim" href="#toc">Gameplay mode: Stimulation / Calming mode</a> + +If you just need something to stimulate your mind to keep you calm or simply you +want to play a game without having to worry about winning or losing you can set +the growth size to 0 and then just move the snake round and round eating bugs +until you want to quit. You can enable cannibalism so that you don't have to +worry about even running into yourself and losing: + + GROW=0 CANNIBAL=1 ./prog + + +## <a name="expansibility" href="#toc">Gameplay mode: Expansibility</a> + +As I was writing this document and the game modes I have thought of other game +modes (they were added) and I have come back to this document to add more modes. +That's the beauty of the variables I have implemented: together with the +imagination and even just chance different modes of play can be devised. The +drawing mode was a happy chance of how the `timeout()` function works for +example. + +As a person who was heavily involved in MUD development and design I know very +well how games need to be fun and have different options, not be too easy but +not be too hard either. And a game developer who does not play their games is a +game developer who is detached from their player base and the wants and needs +are therefore disregarded if even heard. I have played this game a lot for this +reason as well as I simply enjoy it and thinking up new modes. + + +# 5. <a name="scripts" href="#toc">Scripts</a> + +The following scripts are provided to simplify and automate some of the things +this file discusses as well as allowing to easily change the colours. + +## <a name="colours" href="#toc">Colours selection: snake-colours</a> + +To do this use the [snake-colours][] script like so: + + ./snake-colours + +If you want to pass in specific variables you can do that too e.g.: + + CANNIBAL=1 ./snake-colours + +The script will prompt you for the colour of the walls, snake head, body and the +bug. + +## <a name="preset" href="#toc">Automate the above gameplay modes</a> + +The [play.sh][] script has the gameplay modes described in this file and is menu +based (there might be differences and some of the modes I include a variation). +The script tests the terminal (allowing you to continue even if problems are +detected), prompts you if you want to select colours (like those in +snake-colours above) and then gives you a list of game modes to play. You can +pass in the game variables but note that if you pass in a variable that the mode +you choose uses then the script will override what you pass in. + +To use you can do something like: + + ./play.sh + +Or to make it so walls are an obstacle: + + WALLS=0 ./play.sh + + +# 6. <a name="variables" href="#toc">Game variables</a> + +The game variables can be used for a variety of things including different +gameplay modes as above but here are some notes about a few of them. + +## <a name="wait" href="#toc">WAIT: Snake speed</a> + +Besides the different game modes if you find it too fast/slow you can change it +to a value that's better for you. Remember it's a wait time so if you want the +snake to move slower you have to increase the wait time! + + +## <a name="evade" href="#toc">EVADE: Bug evasion frequency</a> + +For every **EVADE** snake movements the bug will try and find a new place to +occupy. It might be very close to it and I do not ensure it's a new place at +all. + +Each time the bug is placed the counter will be reset whether from eating the +bug or not reaching it in time. Default 300 moves. + +This can help you get out of a trap but it can also sometimes make it harder. + + +## <a name="sizes" href="#toc">SIZE / MAXSIZE: Initial / Max snake sizes</a> + +997 might be a bit high for many people. Or maybe you don't have enough time. Or +you're not in the mood to lose. Or you want to get close to a size you were last +time but quickly. It might be in conjunction with drawing mode. + +Note on snake size: there's a stated size (in the score line) which is what +the snake will 'populate' in the snake arrays and the visible size: as I have +discussed here and there the snake doesn't grow immediately so it takes time +before the snake is visibly that many characters. In other words just because it +says SIZE 29 doesn't mean it will instantly be 29 characters on the screen. + + +## <a name="growth" href="#toc">GROW / SHEDS : Growth / Shedding sizes</a> + +Similar to the initial size. Notice that the above point on size applies here: +it will take the number of movements before it is 'its full size'. + + + +# 7. <a name="conclusions" href="#toc">Conclusion (and inspirational words for everyone)</a> + +I believe that this file has given more than enough information for anyone to +get an idea of what is possible with my implementation of Snake. I realise also +that most people won't have read this far and that's quite all right; I'm very +thorough and pay attention to details obsessively. Creating this game was a +delight and I am quite proud of what I have done. + +Thank you for whatever level of attention you felt you could or wanted to give +and enjoy it in whatever way you see fit! + +**Much more importantly is that Snake aside I hope I have demonstrated how with +the imagination and creativity almost anything is possible.** This is something +**that applies in our world in every way and *everyone* can do something amazing if +they believe in themselves!** I would have never thought this the case for me +years ago but I know it's true now. **Believe in yourself. Always.** + +[terminals.markdown]: terminals.markdown +[terminals.html]: terminals.html +[troubleshooting.markdown]: troubleshooting.markdown +[troubleshooting.html]: troubleshooting.html +[bugs.markdown]: bugs.markdown +[bugs.html]: bugs.html +[spoilers.markdown]: spoilers.markdown +[snake-colours]: snake-colours +[number of hertz (flashes) per second triggering seizures]: https://www.epilepsysociety.org.uk/photosensitive-epilepsy#.Xjgpwi2ZOgQ +[termcaps.c]: termcaps.c +[cannibalism.log]: cannibalism.log +[crazy.log]: crazy.log +[play.sh]: play.sh + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/ferguson1/halfwidth_vs_fullwidth.png b/ioccc/2020/ferguson1/halfwidth_vs_fullwidth.png new file mode 100644 index 0000000000000000000000000000000000000000..98b81a4a1a0130c3510e3527906ebe74bd23e017 Binary files /dev/null and b/ioccc/2020/ferguson1/halfwidth_vs_fullwidth.png differ diff --git a/ioccc/2020/ferguson1/hint.text b/ioccc/2020/ferguson1/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..214def6fe4c92dd3425fb9312d54a92eabe72cbe --- /dev/null +++ b/ioccc/2020/ferguson1/hint.text @@ -0,0 +1,521 @@ +# Don't tread on me award + +Cody Boone Ferguson <ioccc@xexyl.net> +<https://ioccc.xexyl.net> +Twitter: @xexyl + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + WAIT=100 WALLS=0 CANNIBAL=0 ./prog + # Start pressing some arrow keys + +### Try: + + make test + + WAIT=75 WALLS=1 CANNIBAL=1 ./prog + + ./prog + + SIZE=-1 ./prog + + CANNIBAL=1 WALLS=1 WAIT=50 EVADE=200 ./prog + + WAIT=75 GROW=-1 SIZE=5 CANNIBAL=1 ./prog + + CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 MAXSIZE=10 ./prog + +### Selected Judges Remarks: + +As the [Gadsden flag](https://en.wikipedia.org/wiki/Gadsden_flag) warns, beware of the snake! +This game has a number of configurable pitfalls including walls and snakes. + +There is a good deal of useful documentation that is provided with this entry: + +* gameplay.markdown ([gameplay.html][]) + +Documented game *features*! + +* terminals.markdown ([terminals.html][]) + +Information about terminal capabilities, dimensions (setting and how to restore sanity if it causes any problems) as well as colours (limitations etc.). + +* troubleshooting.markdown ([troubleshooting.html][]) + +Workaround for various game *features* + +* bugs.markdown ([bugs.html][]) + +Bugs and things that might seem like bugs but are not. + +* [chocolate-cake.html][] + +Because most of us could use some *Double-layered Chocolate Fudge Cake*! + +* spoilers.markdown ([spoilers.html][]) + +Read ***ONLY*** if you really must give up trying to de-obfuscate! + +[gameplay.html]: gameplay.html +[terminals.html]: terminals.html +[troubleshooting.html]: troubleshooting.html +[bugs.html]: bugs.html +[chocolate-cake.html]: chocolate-cake.html +[spoilers.html]: spoilers.html + +## Author's comments: +### Feature-rich curses implementation of the Snake game (with many gameplay modes and options) + +Snake has two cheat modes (passable walls and self [cannibalism]), a drawing (or +practising) mode, *can play by itself (**and win!**)*, is coloured (included +[snake-colours.sh][] and [play.sh][] scripts compile in player-selected +colours) and there are many other play modes (many more can be devised with the +imagination and the environmental variables; see [gameplay.markdown][] / +[gameplay.html][] for many examples) and options. You can pause and there's +even a built-in test unit for some features! The following variables change the +game in the following ways (all can be combined): + + +* The speed of the snake (how many milliseconds to **WAIT** for input before + moving; *default 231 milliseconds* and you can move faster by pressing a + direction key quicker or even holding it down). + +* If the bug (to eat) will move (**EVADE**) after user-specified number of snake + moves (*default 300, 0 disables*). + +* If the snake can go through **WALLS** (coming out at the opposite wall) + (*default 1, yes*). + +* If the snake can go through itself (**CANNIBAL**) (*default 0, no*). + +* The initial **SIZE** of the snake (*default 5*). + +* The size the snake must become in order to win the game (**MAXSIZE**, *default 997*). + +* How much to **GROW** each time a bug is eaten (*default 5*, can be negative). + +* How many moves (**SHED**, *default 0, disabled*) before 'stretching' (grow) + (**SHEDS**, *default 5*; can be negative). This is how snakes grow in the wild so is a + misnomer here because snakes don't grow in the manner that the original + Snake game was designed. + + - Exception: if the bug is eaten the counter isn't incremented. + +* A drawing/practising mode (**WAIT** < 0 makes `timeout()` set blocking read). + +* Computer plays the game (**WAIT=0**) **EPILEPSY/STIMULATION OVERLOAD WARNING** + included in the relevant section (this goes for a low **EVADE** value too). + +* Grow-Shrink mode (Positive and Negative Winning) mode (see + [gameplay.markdown][] for more details). + +* The dimensions of the game (this is actually a terminal thing but I document + how to do this and its potential pitfalls) (**LINES** , **COLUMNS**). + +There are no complicated command line invocations; it's just a matter of passing +into the game descriptively named variables and I include a script that sets up +many different gameplay modes ([gameplay.markdown][] and [play.sh][]). + +The [gameplay.markdown][] ([gameplay.html][]) file has all the information on +what the game looks like, how to play, the different types of modes (that I have +thought of so far) including all those in the above list. Along with the +[play.sh][] and [snake-colours.sh][] scripts it's probably the most important +file for players. + +The gameplay file is long but it includes game printouts as well as explaining +the many different gameplay modes. The [play.sh][] script automates most (if +not all) of the gameplay modes described in the gameplay file (it also +allows you to change colours like [snake-colours.sh][]) as well as the judges' +suggestions (that I don't document so as to not spoil them). You can pass in +environmental variables to both scripts though obviously some will conflict with +different options in play.sh. + +Probably just as important is [chocolate-cake.html][] with an old but wonderful +recipe (because the judges love chocolate and who can blame them? - also it goes +with one of the IAQs I include later). + +The [troubleshooting.markdown][] ([troubleshooting.html][]) file has some advice +on potential problems (and things that might appear to be problems at first +glance but are not) that I have thought of or encountered. + +The [terminals.markdown][] ([terminals.html][]) has a variety of information +specific to terminals from input/directions, dimensions, sanity and colours: a +sort of troubleshooting guide for terminals with some additional information. + +The [spoilers.markdown][] has a variety of information including some of the +obfuscation techniques and a bit of how it works. + +The [bugs.markdown][] ([bugs.html][]) has a list of known bugs and things that +look like bugs but aren't as well as documenting a built-in test unit for some +features. + +Because all IOCCC entries should have a man page I have included one (even +though much of it is what's also above). To render try: + + man ./snake.1 + + +The [COMPILING][] file has a few portability notes and the [HACKING][] file has +some information on how one might modify things, things that could be +implemented (and how to/how not to go about some of the things) as well as some +other information on the entry (some of which is deliberately not true - a +variation of misleading comments). These files are probably insignificant. + +I will have more information about this entry at +[https://ioccc.xexyl.net/2020/snake][] after the winning entries have been +published. + +For the files I recommend looking at the html files with a browser; this +particularly goes for the [gameplay.html][], [bugs.html][], [terminals.html][] +and [troubleshooting.html][] - along with the most important one +[chocolate-cake.html][]. + + +<a name="toc"></a> + +* ['Bugs'](#bugs) + +* [NAQs/IAQs (Never/Infrequently Asked Questions)](#naqs) + - [Do I have any inspirations for this entry?](#inspirations) + - [Are there any features I thought of that I wanted to implement but did not get to for some reason or another?](#features) + - [Are there ways that one can make this game easier?](#easier) + - [Are there ways to make it harder?](#harder) + - [How do snakes grow in real life?](#moult) + - [Any other interesting things about snakes?](#other) + - [Why can you go the opposite direction and so immediately die when not cannibalising?](#opposite) + - [Do you have any **DELICIOUS CHOCOLATE CAKE** recipes?](#chocolatecake) + - [What are the files prog.orig.c, prog.2.c, prog-j.c and prog.alt.c ?](#alt) + +* [Winning thoughts, dedications and thanks](#winning) + + +### <a name="bugs" href="#toc">'Bugs'</a> + +* 'The screen keeps showing bugs!' Well yes, that's rather the point! Help out + by eating them. Keep eating them until you win! Then you will have the + satisfaction of getting rid of the non-bug bugs! :) + +* The Snake in the game doesn't fly (yes there are [flying snakes][]). For + other snake madness see the reports of '[human snakes][]'. + +* Technically walls, snakeskin and the snake itself would not be an obstacle + in real life. The shed snakeskin is not an obstacle but walls can be and + so can the snake itself. Also snakes grow by moulting (technical term for + shedding) so when the snake leaves its snakeskin behind it really ought to + grow but instead it shrinks; this means negative shedding ought to have the + snake grow and positive shedding have the snake - what? It's a misnomer: it + took fewer bytes and the negative shedding is a positive consequence of + unsigned arithmetic. + +On a more serious note look at [bugs.markdown][] ([bugs.html][]). + + +### <a name="naqs" href="#toc">NAQs/IAQs (Never/Infrequently Asked Questions)</a> + +#### <a name="inspirations" href="#toc">Do I have any inspirations for this entry?</a> + +There are two in particular. First is a long time mate of mine wrote a bash +implementation of Snake several years ago (uncoloured, no cheat modes, hardcoded +dimensions etc. - in fact everything was hardcoded). + +Back then I had thought of making a curses implementation of it but I never got +round to it. When the judges announced that the 2020 IOCCC contest would be open +from late December 2019 through 15 March 2020 I started thinking again on what +might be a good entry. By chance I thought of the Snake game and so wrote it +finishing the implementation of everything on 8 November 2019. Did I say +everything? That's an unintentional lie; I thought it was everything but I +implemented many new things after that. In fact I have numerous times thought I +was done only to have added yet another feature - or two or three or more! + +Second is the old Atari game [Surround][]. There were a few modes as I recall. +The object of the game was to surround your opponent so that they would run into +you, the wall or themselves. The opponent was either the computer or another +player. + +In one mode you could go through walls (that's where I got the idea to do +likewise). There was also a drawing mode where you could just move round making +different designs though that this is in my entry is a happy coincidence +(because `timeout()` will block when it gets a negative value). It's true that +in my Snake it's not quite the same but it's close enough. Perhaps it can be +made more like Surround if it grows every movement but then depending on the max +size of the snake the game might be over fairly quickly (I don't remember how +it was done in Surround). + +In Surround each move you made you would grow in size by one. This is what +inspired the shedding mode. Anyway I always loved the game and it's similar to +Snake in several ways. + + +#### <a name="features" href="#toc">Are there any features I thought of that I wanted to implement but did not get to for some reason or another?</a> + +Yes. I thought it would be fun if there were other obstacles for the snake (in +my mind I was thinking of barriers like the walls but in the field). + +I also thought it would be fun to have more than one bug at some point after say +the snake gets to be some size. One of the reasons I didn't do this is because I +was trying to save iocccsize bytes. I never got round to this though and I feel +that the features I have implemented are far more interesting and fun. + +Another idea is having portals or teleportation but there are a number of +problems with those that would have to be worked out too. + +I would have loved for it to be practical to support diagonal movement but as I +describe elsewhere it's not. That's perhaps what I regret most. It would be +possible to choose letters instead of arrow keys but even if that fit in the +size restrictions how would I show the head? I looked at the extended ncurses +character set and I didn't see any diagonal arrows. I suppose I could have it +not show the arrows but then that brings an old problem back. + +Nevertheless I am quite happy with the features in the game and I hope everyone +who plays it enjoys it as much as I enjoyed writing/playing it. + + +#### <a name="easier" href="#toc">Are there ways that one can make this game easier?</a> + +I can think of at the least the following: + + +- Bigger screen will allow for freer movement (at least for more time?). +- Increasing the movement (key press) wait to give you more time to choose + (though this slows gameplay down). +- Decrease the size of the snake (and growth size) though over time the size + will become more and more problematic. But see the next item. +- If you set a high growth size you don't have to worry as much about running + into a wall or the snake itself for as long: because the check if you win is + done when the snake size is increased: if you're 15 away from the max and + each bug you eat you grow by 11 then it won't take as many bugs to win as it + would if the grow size was 3. This applies to shedding size too. +- If you want to show off keep walls passable and enable cannibalism. It + won't be a challenge then but at least you could show your final score? +- Decrease the max size. +- And the one that applies to learning new things and getting more things done + also applies here: remove all sources of distraction; turn the phone off, + lock yourself in a soundproof room (refusing to get up for anyone or + anything) and delete all your social media accounts for starters. Okay you + don't really have to do the latter one but it can't be denied that they can + be very distracting! As can phone (calls and otherwise). And visitors + calling. And being on this planet. +- If you don't want a challenge at all you could just set the start size to be + the max size or very close to it. In fact if you have the shedding size to be + even one on every move even if you normally can't win with the same size + screen you might find it happens much more easily! You could of course play + with these paramters in different ways together - there are certainly + different combinations than I have given. +- Of course you could also enable one or both cheat modes. You might be + considered a filthy cheat but both modes are quite fun (one being enabled by + default; does that mean it's not actually a cheat mode?). + + +#### <a name="harder" href="#toc">Are there ways to make it harder?</a> + +- Decrease the size of the game. +- Decrease the size of the snake growth (and initial snake size). +- Make the snake go faster (decrease the time the game waits for input). +- Hold down the direction keys to move faster; this is something I do often + though I have always had extremely fast reflexes and amazing eye hand + coordination (at least after glasses and the three eye surgeries?). + Admittedly I don't find this makes it any harder but it does make you have + to react faster. +- Be reckless (i.e. increase the chance of a wreck, a most amusing + contradictory idea if you ignore etymology). +- Look away for a moment every so often or have a conversation with your best + mate, partner or family member whilst playing. +- Make walls impassable and disable cannibalism. +- Make the bug move more frequently (this can be a real problem when you can't + go through the walls!). +- Get used to going through walls and then try with it disabled. +- Set the max size to the maximum (*`MAXSIZE=-1`* should do it). + +And if you're a show-off you can try: + +- Closing your eyes (maybe better to practise with one eye open first or even + in practice that is drawing mode?). +- Have someone tickle you. +- Watch a comedy show or have a laugh with a mate or partner or family member. +- Have your partner tease you. +- Speak on the phone with someone (paying attention to both). Come to think of + it I have actually done this though not to show off but rather it's just + something I'm capable of... +- Watch a film at the same time. +- Sneeze and/or cough. +- Have breakfast, lunch, afternoon tea, dinner or some other meal. +- Get pissed out of your mind to make it difficult to think (please do not + drive!). +- Do more than one or all of the above at the same time (the longer the snake + becomes the more often you should do these things). +- Eat a [great chocolate cake][]. Actually you should do that whether you're + trying to show off or not. Sleep, bathe, eat chocolate cake, play Snake, eat + chocolate cake, play Snake, sleep, ... For a great recipe see below. + +But if that's not enough I don't know what to tell you other than suggest that +you make use of your talents for financial gain or at least a world record. +Either way I tip my proverbial snakeskin hat to you (animal cruelty but a pun is +a pun and every pun deserves to be shed). + + +#### <a name="moult" href="#toc">How do snakes grow in real life?</a> + +They grow through a process called moulting - shedding their skin (other +creatures also moult). This takes place over some days and unlike humans snakes +never stop growing (though growth slows down as they mature). I chose the +variables **SHED** and **SHEDS** for simplicity and because the words are +shorter. I don't like the words because it's rather a misnomer but what I had +chosen before was longer - STRETCH and STRETCHES. + +#### <a name="other" href="#toc">Any other interesting things about snakes?</a> + +For the fascinating science behind snake slithering see [Snake walk: The physics +of slithering][]. For the bizarre thought of snake human hybrids see [human +snakes][]. The latter is hard to comprehend and there are some sad tails (tales) +in there too because I believe that people actually believe in this (how/why I +do not know) and they really do tell the truth as they see it (even if +impossible). + +#### <a name="opposite" href="#toc">Why can you go the opposite direction and so immediately die when not cannibalising?</a> + +When Ilya Kurdyukov was playing with this he questioned why this is possible +when other implementations don't have it this way. There are a few reasons. + +First is that the friend's implementation had it that way and it had been a long +time since I had played it (if I ever did? I don't know now: I played so many +games over the years and the game most alike it that I played is Surround, as +below). + +It also is the way it is in Surround. + +It makes cannibalism mode very interesting. + +And I happen to like it the way I have it. In the end a snake isn't an obstacle +for itself but in the game it is and I went all the way instead of only halfway. + +It also would take more bytes and that's a problem with IOCCC rule 2b. + +But if you have a problem with it you can always enable cannibalism and keep +walls passable and not worry about dying. + + +#### <a name="chocolatecake" href="#toc">Do you have any **DELICIOUS CHOCOLATE CAKE** recipes?</a> + +Why yes I do! So good in fact that even my late stepmum who didn't even like +chocolate (except white chocolate) loved this cake. It's a double-layered +chocolate fudge cake. See the file [chocolate-cake.html][] for the recipe. +Note that it's a complicated but it's well worth it! + +I included it in all my entries this year because if any of them won more people +can have this recipe; also it might help remind the judges that they really +should have their cook bake it so they can all - including the cook should they +also like chocolate - enjoy the cake whilst judging (and otherwise - it's a big +cake and very rich). Sadly they didn't get to enjoy it during their judging due +to the pandemic but maybe next time (or they can do on their own). + +Do make sure to pay attention to all notes! + +##### A note on the icing and room temperature + +Please be advised that the note there that talks about the icing being difficult +in too warm room is rather significant; unfortunately with SARS-CoV-2 this might +be more of a problem depending on how long it lasts and where you reside. If +necessary use the refrigerator or else air conditioner to cool down the place. + + +#### <a name="alt" href="#toc">What are the files prog.2.c, prog.3.c, prog.3-j.c and prog.alt.c ?</a> + +I submitted three Snake versions; these are the other layouts for those few +(or more likely none) who are interested to see them. + +The prog.2.c has more digraphs but I think no other significant differences. + +The prog.3.c is in a more artistic layout (a backwards S), has at least one +additional obfuscation technique (see spoilers) but it also has more digraphs +and as the judges said they feel that digraphs are dated so that's probably why +they chose the first layout. The prog.3-j.c version is prog.3.c with a shorter J +define. + +The prog.alt.c version is the one that allows for customising the bug colour and +it's used in both [snake-colours.sh][] and [play.sh][]. It also calls `erase()` +first, clearing the screen, which the play.sh and snake-colours.sh scripts also +both do. + +[COMPILING]: COMPILING +[HACKING]: HACKING +[bugs.markdown]: bugs.markdown +[bugs.html]: bugs.html +[troubleshooting.markdown]: troubleshooting.markdown +[troubleshooting.html]: troubleshooting.html +[human snakes]: http://www.macroevolution.net/snake-human-hybrids.html +[chocolate-cake.html]: chocolate-cake.html +[spoilers.markdown]: spoilers.markdown +[terminals.markdown]: terminals.markdown +[Surround]: https://en.wikipedia.org/wiki/Surround_(video_game) +[Snake walk: The physics of slithering]: https://www.bbc.co.uk/news/science-environment-35563941 +[snake-colours.sh]: snake-colours.sh +[gameplay.markdown]: gameplay.markdown +[gameplay.html]: gameplay.html +[flying snakes]: https://www.bbc.co.uk/news/science-environment-25943693 +[play.sh]: play.sh +[great chocolate cake]: cake.jpg +[https://ioccc.xexyl.net/2020/snake]: https://ioccc.xexyl.net/2020/snake + +## Author's dedication: + +### <a name="winning" href="#toc">Winning thoughts, dedications and thanks</a> + +Once again I'm honoured to win along with some of the other veterans who I have +a huge amount of respect for; there's Don Yang, Dave Burton, Yusuke Endoh and +Edward Giles all of whom are amazing programmers. I'm especially proud to win +besides Dave Burton and Yusuke Endoh but Don Yang and Edward Giles too. + +But there are some others who I don't remember like Ilya Kurdyukov (who's +offered a lot of interesting thoughts on Snake and who plans to have his own +version after the entries are published), Nathan Otterness, Nicholas Carlini +(whose entry is an absolutely brilliant abuse of printf - and I totally agree +with the judges comments that your entry is so novel that it'll be worth special +mention in the future Best of IOCCC list!) and tsoj too. + +Well done and congratulations to all of you again! Thank you for submitting the +wonderful entries and I'm honoured to have my two entries beside yours! + +To Dave Burton I thank you for your wonderful comments as well as pointing out +that even with prog.orig.c it probably would be better to make use of the alt +target instead of naming prog.c prog.orig.c. You're quite right, I had thought +of it but you brought it up so I could correct it. Much appreciated mate. + +I would like to dedicate this entry to my wonderful mum Dianne Ferguson whom I +love with all my heart and soul <3 Thank you for being the best mother +imaginable! You've been there for me in the darkest of my hours without question +without complaint and with all the love, compassion, empathy, sympathy and +devotion anyone could ever ask for. Bless you again and again and again dear +mother. + +I would like to thank my dear friend Martijn Schoemaker for encouraging me in my +programming over the years and who I owe a great deal to. Thank you for +believing in me and my programming abilities (and other abilities) even when I +couldn't believe in myself! Very much appreciated especially coming from an +amazing programmer who I have huge admiration for! + +I want to thank Ilya Kurdyukov for his helpful comments, suggestions and +reporting the problem about half-width/full-width char spacing. He's been +playing with some versions of his own and will have them on GitHub after the +2020 IOCCC winning entries have been published. + +Finally I want to thank Leo Broukhis, Simon Cooper and Landon Curt Noll for +continuing to hold the contest after all these years - and for having selected +my entries. It's a huge honour; thank you! I also happen to **love** your +comments as well as the award titles. And yes indeed 'most of us could use +*[Double-layered Chocolate Fudge Cake][]*!' + + +[Double-layered Chocolate Fudge Cake]: chocolate-cake.html + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/ferguson1/ioccc-cake.jpg b/ioccc/2020/ferguson1/ioccc-cake.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6825698170ddadac7dc511e3ce3a32f7f4bea24f Binary files /dev/null and b/ioccc/2020/ferguson1/ioccc-cake.jpg differ diff --git a/ioccc/2020/ferguson1/play.sh b/ioccc/2020/ferguson1/play.sh new file mode 100644 index 0000000000000000000000000000000000000000..9e464c784353246fa4277649371ba5a2bc0c01a6 --- /dev/null +++ b/ioccc/2020/ferguson1/play.sh @@ -0,0 +1,276 @@ +#!/bin/bash +# +# SCRIPT TO PLAY PRESET GAMEPLAY MODES +# +# The easiest way to see what this script does is to simply run it; however you +# can pass in variables but depending on what mode you select it might be +# overridden so that the variable you pass in doesn't take effect. You can of +# course modify this script otherwise. +# +# This script first runs make and then termcaps (the terminal capability test +# utility); if any problems are detected it prompts if you wish to proceed. +# Assuming no problems or you proceed anyway it then asks you if you want to +# configure the colours of the walls, snake head and body as well as the bug. +# Then it gives you a menu of gameplay modes. +# +# Let's say you want to enable cannibalism but don't want to be able to go +# through walls in hypnotic mode. Just type: +# +# CANNIBAL=1 WALLS=0 ./play.sh +# +# And you would then choose mode 5. +# +# This script could be further improved to prompt the different variables but +# that would complicate it much further and I'm not sure what should be done +# about variables that would cancel the mode requested. +# +# As for drawing mode what if you don't want to ever end up 'winning'? In this +# case you'll probably want to set the initial size to be rather high and growth +# to 0. You could also play with the idea of setting a growth value but setting +# negative shedding (or the other way round). For example: +# +# SIZE=400 SHED=100 SHEDS=-5 ./play.sh +# +# This is actually option 1 since this seemed like a good addition to the script +# (added 16 August 2020). This will start you at 400 and every 100 movements you +# would lose 5 in length; when you eat a bug you would grow by 5 (default). +# +# Last updated: 16 August 2020 +COLOUR[0]="BLACK" +COLOUR[1]="RED" +COLOUR[2]="GREEN" +COLOUR[3]="YELLOW" +COLOUR[4]="BLUE" +COLOUR[5]="MAGENTA" +COLOUR[6]="CYAN" +COLOUR[7]="WHITE" +DFLT[0]="-DWALL=COLOR_CYAN" # Wall foreground: cyan (WALL) +DFLT[1]="-DWB=COLOR_BLACK" # Wall background: black (WB) +DFLT[2]="-DHEAD=COLOR_RED" # Head foreground: red (HEAD) +DFLT[3]="-DHB=COLOR_BLACK" # Head background: black (HB) +DFLT[4]="-DBODY=COLOR_GREEN" # Body foreground: green (BODY) +DFLT[5]="-DBS=COLOR_BLACK" # Body background: black (BS) +DFLT[6]="-DBG=COLOR_WHITE" # Bug foreground: white (BG) +DFLT[7]="-DBB=COLOR_BLACK" # Bug background: black (BB) +COLOURS[0]="-DWALL=COLOR_" +COLOURS[1]="-DWB=COLOR_" +COLOURS[2]="-DHEAD=COLOR_" +COLOURS[3]="-DHB=COLOR_" +COLOURS[4]="-DBODY=COLOR_" +COLOURS[5]="-DBS=COLOR_" +COLOURS[6]="-DBG=COLOR_" +COLOURS[7]="-DBB=COLOR_" + +function show_colours() +{ + echo "Colour selection for ${*} (enter for default)" + for i in 0 1 2 3 4 5 6 7; do + printf "(%d) %s\n" "${i}" "${COLOUR[${i}]}" + done + read -rp "Make selection (1 - 7): " colour + + case "${colour}" in + 0|1|2|3|4|5|6|7) + return "${colour}" + ;; + *) + return 255 + ;; + esac +} +function configure_colours() +{ + j=0 + for i in "WALL" "WALL (BACKGROUND)" "HEAD" "HEAD (BACKGROUND)" "BODY" "BODY (BACKGROUND)" "BUG" "BUG (BACKGROUND)"; do + show_colours "${i}" + x="${?}" + if [ "${x}" != 255 ]; then + COLOURS[$j]="${COLOURS[$j]}${COLOUR[$x]}" + else + COLOURS[$j]=${DFLT[$j]} + fi + j=$j+1 + done + + echo cc -o prog.alt prog.alt.c -D'f(a,b)'='((a)<(b)?(a):(b))' ${COLOURS[0]} ${COLOURS[1]} \ + ${COLOURS[2]} ${COLOURS[3]} ${COLOURS[4]} ${COLOURS[5]} ${COLOURS[6]} ${COLOURS[7]} -lncurses + + cc -o prog.alt prog.alt.c -D'f(a,b)'='((a)<(b)?(a):(b))' ${COLOURS[0]} ${COLOURS[1]} \ + ${COLOURS[2]} ${COLOURS[3]} ${COLOURS[4]} ${COLOURS[5]} ${COLOURS[6]} ${COLOURS[7]} -lncurses || exit 1 +} +function testcaps() +{ + make || exit 1 + ./termcaps + T="${?}" + if [ "${T}" -ne 0 ]; then + read -rp "Terminal issues detected; do you wish to continue anyway (Y/N) ? " ans + [[ "${ans}" != "y" ]] && [[ "${ans}" != "Y" ]] && exit 1 + fi +} +function menu() +{ + printf "** GAME MODE SELECTION MENU **\n\n" + + echo "(0) Drawing mode" + echo "(1) Drawing mode #2 (start at 400 and shrink by 5 every 100 moves)" + echo "(2) Computer plays by itself (EPILEPSY / STIMULATION OVERLOAD TRIGGER)" + echo "(3) Computer plays by itself #2 (EPILEPSY / STIMULATION OVERLOAD TRIGGER)" + echo "(4) Grow / Shrink mode" + echo "(5) Grow / Shrink mode #2" + echo "(6) Hypnotic mode (EPILEPSY / STIMULATION OVERLOAD TRIGGER)" + echo "(7) Stimulation / Calming mode" + echo "(8) Normal mode (aka Judges' Normal)" + echo "(9) 100ms w/o cheat modes (Judges' Zeroth)" + echo "(10) 75ms w/both cheat modes (Judges' First)" + echo "(11) Immediately win (Judges' Second)" + echo "(12) 50ms w/both cheat modes, evade at 200 moves (Judges' Third)" + echo "(13) 75ms w/both cheat modes, shrink mode (win with six bugs) (Judges' Fourth)" + echo "(14) Let computer win by itself very quickly (Judges' Fifth)" + echo "(15) Start at 400, shrink by 5 every 100 moves, cannibalism, max size possible" + echo "(16) Start at 400, shrink by 5 every 100 moves, max size possible" + echo "" +} +PROG="./prog.alt" +function judges0() +{ + clear && WAIT=100 WALLS=0 CANNIBAL=0 ${PROG} +} +function judges1() +{ + clear && WAIT=75 WALLS=1 CANNIBAL=1 ${PROG} +} +function judges2() +{ + clear && SIZE=-1 ${PROG} +} +function judges3() +{ + clear && CANNIBAL=1 WALLS=1 WAIT=50 EVADE=200 ${PROG} +} +function judges4() +{ + clear && WAIT=75 GROW=-1 SIZE=5 CANNIBAL=1 ${PROG} +} +function judges5() +{ + clear && CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 MAXSIZE=10 ${PROG} +} +function draw0() +{ + clear && MAXSIZE=-1 WAIT=-1 CANNIBAL=1 ${PROG} +} +function draw1() +{ + clear && MAXSIZE=-1 WAIT=-1 CANNIBAL=1 SIZE=400 SHED=100 SHEDS=-5 ${PROG} +} +function growshrink3() +{ + clear && MAXSIZE=-1 CANNIBAL=1 SIZE=400 SHED=100 SHEDS=-5 ${PROG} +} +function growshrink4() +{ + clear && MAXSIZE=-1 SIZE=400 SHED=100 SHEDS=-5 ${PROG} +} +function auto0() +{ + clear && WAIT=0 EVADE=1 CANNIBAL=1 MAXSIZE=20 ${PROG} +} +function auto1() +{ + clear && WAIT=0 EVADE=1 GROW=-1 SIZE=9 MAXSIZE=10 CANNIBAL=1 ${PROG} +} +function growshrink0() +{ + clear && SIZE=150 SHEDS=-5 GROW=10 SHED=50 MAXSIZE=250 ${PROG} +} +function growshrink1() +{ + clear && SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ${PROG} +} +function hypno() +{ + clear && EVADE=1 CANNIBAL=1 ${PROG} +} +function stim() +{ + clear && GROW=0 CANNIBAL=1 ${PROG} +} +function norm() +{ + clear && ${PROG} +} +function play() +{ + testcaps + + read -rp "Do you want to configure colours (Y/N) ? " colours + + case "${colours}" in + y|Y) + configure_colours + ;; + *) + ;; + esac + + menu + read -rp "Make your selection (0 - 7 or any other key to exit): " mode + + case "${mode}" in + 0) # Drawing mode 0 + draw0 + ;; + 1) # Drawing mode 1 + draw1 + ;; + 2) # Automatic mode (computer plays by itself) (photosensitive epilepsy/stimulation overload trigger) + auto0 + ;; + 3) # Automatic mode variation 0 (photosensitive epilepsy/stimulation overload trigger) + auto1 + ;; + 4) # grow shrink mode + growshrink0 + ;; + 5) # grow shrink mode variation 0 + growshrink1 + ;; + 6) # hypnotic mode (photosensitive epilepsy/stimulation overload trigger) + hypno + ;; + 7) # stimulation / calming mode + stim + ;; + 8) # normal mode (aka Judges' Normal) + norm + ;; + 9) # 100ms w/o cheat modes (Judges' Zeroth) + judges0 + ;; + 10) # 75ms w/both cheat modes (Judges' First) + judges1 + ;; + 11) # Immediately win (Judges' Second) + judges2 + ;; + 12) # 50ms w/both cheat modes, evade at 200 moves (Judges' Third) + judges3 + ;; + 13) # 75ms w/both cheat modes, shrink mode (win with six bugs) (Judges' Fourth) + judges4 + ;; + 14) # Let computer win by itself very quickly (Judges' Fifth) + judges5 + ;; + 15) # Start at 400, shrink by 5 every 100 moves, cannibalism and max size possible + growshrink3 + ;; + 16) # Start at 400, shrink by 5 every 100 moves and max size possible + growshrink4 + ;; + *) + exit 0 + esac +} +play diff --git a/ioccc/2020/ferguson1/prog.2.c b/ioccc/2020/ferguson1/prog.2.c new file mode 100644 index 0000000000000000000000000000000000000000..3b309d21bba1864a6b5b5a97ab6d78a60d643d50 --- /dev/null +++ b/ioccc/2020/ferguson1/prog.2.c @@ -0,0 +1,53 @@ + %:include<curses.h> + %:include<unistd.h> + %:include<time.h> + + + %:include<stdlib.h> + %:define d =strtoul(z,NULL,0)); + %:define m(n)COLOR_%:%:n + %:define v stdscr + %:define q mvaddch( + + + %:define Z(x)%:x + %:define F(x)z=getenv(Z(x)); z&&( + %:define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n),Y,y<:-2:>,X,*y,A,g,c); + + + typedef size_t a; typedef unsigned long k; a g=997, c,A=5,I,N=5,G=5; k p <: 5 :> = <% 1 %>,W= + 300; int Y,X,*j=( int<:8 :>)<% 231 %>,*U,*V,*e,*n,Q ,P,x,*y,l = 4, *D; void b(a h) <% c += h ; + mvprintw(0,0, J %> int E(const char* L)<%static int h ; ! h && endwin(); h=l; L&&puts(L); return + 1; %>void C (int L ,int h)<%attroff( m ( PAIR(L))); h &&attron(m(PAIR(L) )); %>int R(int h,int L) + <% return (rand()% (L-h+1)) + h; %> void S (a o) <% static const char* s=Z (; +<>^v); q n<:0:>, + e<:0:>,' '); A =f( A+o,g); if (A>=g) <%E(Z(YOU WIN!)) ; Q=l; return; %>C (3, 1); for(I=0; A&&I<A- + 1; ++I)<%I&& q n<: I:>,e<:I:>,'o') ; e<:I:> = e<:I +1 :>; n<:I:>=n<:I+1 :>; %>A>1&&q n<:I:>,e<:I + + :>, 'o'); e<:I:> = Y; n <: I :> = X; while(++I<g) e<: I:>=n<:I:> = 0; C( 2,1); q X,Y,s<:*D+2&(1<< + 3)- !Q:>); %> void B(a o)<%if (o)<% S(N); b(1); %>if (Q) return; p<:1:> = 0; !o &&q*U,*V,' '); x + :y<:3:>=R(1,y <:-2 :>-1); y<:2:>= R( 2,*y-1); for (I= 0; I<A; ++I)if (*V == e<:I:>&& *U == n<:I:> + ) goto x; %> int main(void)<%char* z; y=j+3; void(* H<::>) (a)=<%b,S,B %>; srand((unsigned)time + ( NULL ) ); if (! initscr()) return 1; getmaxyx(v,*y ,y<:-2:> ); -- *y; -- y<:-2:>; if(y<:-2:><9 + || *y < 9) return E ( Z ( term too small) ) ; F ( MAXSIZE)g d g =f(( a)((*y-2)*(y<:-2:>-2)),g + ); F(GROW)N d F( SIZE) A d F(WAIT) y<: - 3 :>= (int )strtol(z,NULL,0)) ; F(EVADE)W d U=y+ 2; F( + WALLS) * p d F( CANNIBAL) p<:4:>d F(SHED)p<:3:>d F (SHEDS) G d e = calloc(g+1,sizeof*e); n= + calloc(g+1,sizeof* n); if (!e||!n) return E ( Z ( memory error)); V= U+1; Y= y<:-2:>/2; X=*y/ + 2; D=1+V; attron ( A_BOLD); curs_set ( 0 ) ; nonl (); intrflush(v, 0) ; keypad(v,1); noecho (); + cbreak ( ) ; start_color () ; init_pair(1,WALL , WB); init_pair( 2,HEAD,HB); init_pair(3, + + BODY,BS); S(0); B(0) ; x: if(Q) + #undef d + + goto y; x = *y ; getmaxyx(v,1<:y:> ,y<:-1:>); C(1,1 ); mvhline(1,0,'#' ,y<:-2:>); mvvline (1,0, + '#',*y); mvhline(* y,0, '#', y<:-2:> ); mvvline(1,y<: -2:>,'#',*y); C(1, 0); q*U, *V,'*'); (*H)(0 + ) ; refresh () ; timeout (y<:-3:>) ; switch (getch( ))<%case KEY_LEFT: V<:1:>=l-3; break ; case + KEY_RIGHT:V<:l/l:> =l/2; break; case KEY_UP:V<:l-3:>= l-1; break; case KEY_DOWN:V <:l / 4:> = l + ; break; case 'q': case 'Q' : Q = l; case' ':(!P && ( P = 1) ) || (P=0); default:x=0; %> if(x)P = + !*y;if(Q||P)goto x ; if(!Q&& !1<:V:> )goto x; switch( 1<:V:>)<%case 1:-- Y; break; case 2 : ++ Y; + break; case 3:--X; break; case 4: ++ X; break; %>if(Y <1 || Y >= y<:-2:> || X < 2|| X >= *y ||y<: + -2:>>=y<:-1:> ||*y >=1<:y:>)<%if (*p &&!(*y>=1<:y:>|| y<:-2:>>=y<:-1:>)) <%if(Y<1||Y >=y <:-2:>)Y + =Y<1?y<:-2:>-1:1 ; if(X<2||X>=*y)X=X <2? * y-1:2; %> else<% E(Z(OUCH!)) ; goto y; %>%>for (I =0; + !4<:p:> && I<A; ++ I)if (Y == e<:I:> && X==n<:I:>)<%E (Z(OW!)); goto y; %>if (Y == *V && X == *U + ) B(1); else <% if (W&&!(++1<:p:> % W))H<:2:>(0); if (3<:p:>)<% if (! ( ++p<:2:>%3<:p:>)) <%H<:1 + :> (G); 2 <: p :>=0; %> else S (0); %>else S (0); %> goto x; y : E (NULL ); printf( + J free(e); free(n); return 0; %> diff --git a/ioccc/2020/ferguson1/prog.3-j.c b/ioccc/2020/ferguson1/prog.3-j.c new file mode 100644 index 0000000000000000000000000000000000000000..77ce56d24a4f1dc88051e4a033cfe90414bb8b15 --- /dev/null +++ b/ioccc/2020/ferguson1/prog.3-j.c @@ -0,0 +1,71 @@ + %: include <curses.h> + %: include <unistd.h> + %: include <time.h> + %: include <stdlib.h> + + %: define d =strtoul(z,NULL,0)); + %: define m(n)COLOR_%:%:n + %: define v stdscr + %: define q mvaddch( + %: define Z(x) %:x + %: define F(x) z = getenv(Z(x)); z&&( + %: define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n),Y, y<:-2\ + :>,X,*y,A,g,c); + %: define f(a,b) ((a)<(b)?(a):(b)) + + typedef size_t a; typedef unsigned long k; a g=997,c,A=5,I,N=5 + ,G=5; k p<:5:>={ 1} , W =300; int l,Y,X,*j=(int<:8:>){ 231} ,* + U,*V,*e,*n,Q,P,x,* y, *D; void b(a h){ c +=h; mvprintw(0,0,J } + int E(const char * L){ static int h; !h && endwin(); h=*y; L&& + puts(L) ; return 1; } void C(int L, int h) { attroff(m(PAIR(L + ))); h && attron(m(PAIR(L))); } int R(int h, int L) { return + (rand()%(L-h+1)) + h ;} void S(a o) { static const char *s =Z + ( ; +<>^v); q n <:0:>,e<: 0:>,' '); A=f(A+o,g); if(A>=g){ E(Z( + YOU WIN! ) ) ; Q = l; return ; } C(3,1); for (I=0; A &&I<A-(A + -A||A); ++I){ I&&q n<:I:>,e<: I:>,'o') ; e<:I:>= e<:I+1:>; n<: + I:>=n<: I +1:>; } A>1&&q n<:I:>,e<:I:>,'o'); e<:I:>=Y; n<:I:>= + X; while(++I<g)e<:I:>=n<:I:>=0; C + (2,1); q X,Y,s<:*D+2&(1<<3)-!Q:>) + ; } void B(a o){ if(o){ S(N); b(1 + ); } if(Q)return; p<:1:>=0; !o&&q + *U,*V,' '); x:y<:3:>=R(1,y<:-2:>- + 1); y<:2:>=R(2,*y-1); for(I=0; I< + A; ++ I)if (* V==e<:I:>&&*U== n<: + I:>) goto x; } int main(void) { l + =++(int) { 3 } ; char *z; y = j+3 + ; void(*H<::>) (a) = { b, S, B}; + srand((unsigned)time(NULL)); if(! + initscr())return 1; getmaxyx(v,*y,y<:-2:>);--*y; --y<:-2:>; if + (y<:-2:><9||*y<9)return E(Z(screen too small)); F(MAXSIZE) g d + g=f((a)((*y-2)*(y<:-2:>-2)),g); F(GROW)N d F(SIZE)A d F(WAIT)y + <:-3:>=(int)strtol(z,NULL,0)); F(EVADE)W d U=y+2;F(WALLS) *p d + F(CANNIBAL)p<:4:>d F(SHED)p<:3:>d F(SHEDS )G d e=calloc(g + 1, + sizeof*e); n=calloc(g+1,sizeof*n); if(!e||!n)return E(Z(memory + error)); V=U+1; Y=y<:-2:>/2; X=*y/2; D=1 + V; attron(A_BOLD) ; + curs_set(0); nonl(); intrflush(v, 0); keypad (v, 1); noecho(); + cbreak (); start_color (); init_pair(1,WALL, WB); init_pair(2, + HEAD,HB); init_pair(3,BODY,BS); S(0); B(0); x:if(Q)goto y;x=1; + getmaxyx(v,1<:y:>,y<:-1:>); C(1,1); mvhline(1,0,'#',y<:-2:>) ; + mvvline(1,0,'#',*y); mvhline(* + y,0,'#',y<:-2:>);mvvline(1,y<: + -2:>,'#', *y); C(1,0); q*U,*V, + '*' ) ; (*H) (0) ; refresh() ; + timeout(y<:-3:>); switch(getch + ()){ case KEY_LEFT:V<:1:>=l-3; + break; case KEY_RIGHT : V<:l/l + :>=l/2; break; case KEY_UP:V<: + l-3:>=l-1; break;case KEY_DOWN + : V <:l/4:>=l; break; case 'q' + :case'Q':Q=l; case' ':(!P&&(P= + 1))||(P=0); default:x=0; } if( + x)P=0; if(Q||P) goto x ; if(!Q&&!1<:V:>) goto x; switch(1<:V:> + ){ case 1: --Y; break; case 2: ++Y; break; case 3: -- X; break + ; case 4: ++X; break; } if (Y<1||Y>=y<:-2:>||X<2||X>=*y||y<:-2 + :>>=y<: -1 :>|| *y>=1<:y:>){ if(*p&&!(*y>=1<:y:>||y<:-2:>>=y<: + -1:>)){ if(Y <1||Y>=y<:-2:>)Y=Y<1?y<:-2:>-1:1; if(X<2||X>=*y)X + =X<2?*y- 1:2 ; } else{ E(Z(OUCH!)); goto y; } } for(I=0; !4<:p + :>&&I <A; ++I)if(Y == e<:I:>&&X==n<:I:>){ E(Z(OW!)); goto y; } + if(Y== *V &&X==*U)B(1); else{ if(W&& !(++1<:p:>%W) )H<:2:>( + 0) ; if( 3 <:p:>){ if(!( ++p<:2:>% 3<:p:>)){ H <:1:>(G); 2 <:p + :> = 0 ; } else S (0);} else S ( 0); } goto x; y:E( NULL ) ; + printf (J free ( e ); free (n) ; return 0 ;} diff --git a/ioccc/2020/ferguson1/prog.3.c b/ioccc/2020/ferguson1/prog.3.c new file mode 100644 index 0000000000000000000000000000000000000000..4ffb4f19b1405f61a15e90788cddf1bc55197529 --- /dev/null +++ b/ioccc/2020/ferguson1/prog.3.c @@ -0,0 +1,71 @@ + %: include <curses.h> + %: include <unistd.h> + %: include <time.h> + %: include <stdlib.h> + + %: define d =strtoul(z,NULL,0)); + %: define m(n)COLOR_%:%:n + %: define v stdscr + %: define q mvaddch( + %: define Z(x) %:x + %: define F(x) z = getenv(Z(x)); z&&( + %: define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n),Y, y<:-2\ + :>,X,*y,A,g,c + %: define f(a,b) ((a)<(b)?(a):(b)) + + typedef size_t a; typedef unsigned long k; a g=997,c,A=5,I,N=5 + ,G=5; k p<:5:>={ 1} , W =300; int l,Y,X,*j=(int<:8:>){ 231} ,* + U,*V,*e,*n,Q,P,x,* y, *D; void b(a h){ c+=h; mvprintw(0,0,J);} + int E(const char * L){ static int h; !h && endwin(); h=*y; L&& + puts(L) ; return 1; } void C(int L, int h) { attroff(m(PAIR(L + ))); h && attron(m(PAIR(L))); } int R(int h, int L) { return + (rand()%(L-h+1)) + h ; } void S(a o) { static const char *s =Z + ( ; +<>^v); q n <:0:>,e<: 0:>,' '); A=f(A+o,g); if(A>=g){ E(Z( + YOU WIN! ) ) ; Q = l; return ; } C(3,1); for (I=0; A &&I<A-(A + -A||A); ++I){ I&&q n<:I:>,e<: I:>,'o') ; e<:I:>= e<:I+1:>; n<: + I:>=n<: I +1:>; } A>1&&q n<:I:>,e<:I:>,'o'); e<:I:>=Y; n<:I:>= + X; while(++I<g)e<:I:>=n<:I:>=0; C + (2,1); q X,Y,s<:*D+2&(1<<3)-!Q:>) + ; } void B(a o){ if(o){ S(N); b(1 + ); } if(Q)return; p<:1:>=0; !o&&q + *U,*V,' '); x:y<:3:>=R(1,y<:-2:>- + 1); y<:2:>=R(2,*y-1); for(I=0; I< + A; ++ I)if (* V==e<:I:>&&*U== n<: + I:>) goto x; } int main(void) { l + =++(int) { 3 } ; char *z; y = j+3 + ; void(*H<::>) (a) = { b, S, B}; + srand((unsigned)time(NULL)); if(! + initscr())return 1; getmaxyx(v,*y,y<:-2:>);--*y; --y<:-2:>; if + (y<:-2:><9||*y<9)return E(Z(screen too small)); F(MAXSIZE)g d + g=f((a)((*y-2)*(y<:-2:>-2)),g); F(GROW)N d F(SIZE)A d F(WAIT)y + <:-3:>=(int)strtol(z,NULL,0)); F(EVADE)W d U=y+2;F(WALLS) *p d + F(CANNIBAL)p<:4:>d F(SHED)p<:3:>d F(SHEDS )G d e=calloc(g + 1, + sizeof*e); n=calloc(g+1,sizeof*n); if(!e||!n)return E(Z(memory + error)); V=U+1; Y=y<:-2:>/2; X=*y/2; D=1 + V; attron(A_BOLD) ; + curs_set(0); nonl(); intrflush(v, 0); keypad (v, 1); noecho(); + cbreak (); start_color (); init_pair(1,WALL, WB); init_pair(2, + HEAD,HB); init_pair(3,BODY,BS); S(0); B(0); x:if(Q)goto y;x=1; + getmaxyx(v,1<:y:>,y<:-1:>); C(1,1); mvhline(1,0,'#',y<:-2:>) ; + mvvline(1,0,'#',*y); mvhline(* + y,0,'#',y<:-2:>);mvvline(1,y<: + -2:>,'#', *y); C(1,0); q*U,*V, + '*' ) ; (*H) (0) ; refresh() ; + timeout(y<:-3:>); switch(getch + ()){ case KEY_LEFT:V<:1:>=l-3; + break; case KEY_RIGHT : V<:l/l + :>=l/2; break; case KEY_UP:V<: + l-3:>=l-1; break;case KEY_DOWN + : V <:l/4:>=l; break; case 'q' + :case'Q':Q=l; case' ':(!P&&(P= + 1))||(P=0); default:x=0; } if( + x)P=0; if(Q||P) goto x ; if(!Q&&!1<:V:>) goto x; switch(1<:V:> + ){ case 1: --Y; break; case 2: ++Y; break; case 3: -- X; break + ; case 4: ++X; break; } if (Y<1||Y>=y<:-2:>||X<2||X>=*y||y<:-2 + :>>=y<: -1 :>|| *y>=1<:y:>){ if(*p&&!(*y>=1<:y:>||y<:-2:>>=y<: + -1:>)){ if(Y <1||Y>=y<:-2:>)Y=Y<1?y<:-2:>-1:1; if(X<2||X>=*y)X + =X<2?*y- 1:2 ; } else{ E(Z(OUCH!)); goto y; } } for(I=0; !4<:p + :>&&I <A; ++I)if(Y == e<:I:>&&X==n<:I:>){ E(Z(OW!)); goto y; } + if(Y== *V &&X==*U)B(1); else{ if(W&& !(++1<:p:>%W) )H<:2:>( + 0) ; if( 3 <:p:>){ if(!( ++p<:2:>% 3<:p:>)){ H <:1:>(G); 2 <:p + :> = 0 ; } else S (0); } else S ( 0); } goto x; y:E( NULL ) ; + printf (J); free ( e ); free (n) ; return 0 ;} diff --git a/ioccc/2020/ferguson1/prog.alt.c b/ioccc/2020/ferguson1/prog.alt.c new file mode 100644 index 0000000000000000000000000000000000000000..68273c41694bdd5db1402ad878bb7c6a31983294 --- /dev/null +++ b/ioccc/2020/ferguson1/prog.alt.c @@ -0,0 +1,53 @@ + #define d =strtoul(z,NULL,0)); + #define m(n) COLOR_%:%:n + #define v stdscr + + #define q mvaddch( + #define Z(x) %:x + #define F(x)z=getenv(Z(x)); z&&( + #define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n),Y,y[-2],X, *y, A, g, c ); + #include <curses.h> + + #include <unistd.h> + #include <time.h> + #include <stdlib.h> + + typedef size_t a; typedef unsigned long k; static a g= 997,c,A=5,I,N=5 ,G=5; static k p <:5:>= + <% 1 %>,W = 300; static int Y,X,*j =(int<:8])<% 231 %>,*U, *V,*e,*n, Q ,P,x,*y,l=4, * D; static + void b(a h) { c+=h ; mvprintw(0, 0,J } static int E( const char * L)<% static int h; !h&&endwin + (); h=l; L&&puts(L ); return 1; } static void C ( int L, int h) { attroff(m(PAIR(L))); h&& + attron(m(PAIR(L))) ; } static int R (int h, int L) { return (rand () % (L - h + 1))+h; } static + void S(a o){static const char*s =Z( ; +<>^v); q n[0] ,e[0],' '); A = f( A+o,g ); if (A >= g) { + E(Z(YOU WIN!)); Q = l; return; } C( 3, 1); for (I = 0; A && I < A - 1 ; ++I) { I && q n[I], e[ + I], 'o'); e[I] = e [I + 1]; n[I] =n[ I+1]; } A > 1 && q n[I],e[I], 'o'); e[I] = Y; n[I]= X; while + (++I < g) e[I] = n [I] = 0; C(2, 1); q X,Y,s[*D+2& (1 <<3)-!Q]); }static void B(a o){ if (o) { S( + N); b(1); } if (Q) return; p[1] = 0; !o && q*U,*V,' ' ); x: y[3] = R(1,y [-2]-1); y[2] = R(2,*y-1 + ); for (I = 0; I < A; ++I) if (*V == e[I] && *U == n[ I]) goto x; } int main(void) { char *z; y= + + + j+3; void (*H[])(a )={b,S,B} ; srand ((unsigned)time( NULL));if(!initscr ( ) ) return puts (Z ( + curses error)); erase();getmaxyx( v,*y,y[-2]);--*y ;--y[-2];if(y[-2]< 9||*y<9 ) return E (Z + (screen too small) ); F(MAXSIZE)g d g = f((a)((*y-2) *(y[-2]-2)),g); F( GROW)N d F (SIZE) A d F + (WAIT)y [-3]=(int) strtol(z,NULL,0)) ; F(EVADE)W d U= y+2; F(WALLS) *p d F(CANNIBAL)p[4] d F(SHED + ) p[3] d F (SHEDS )G d e = calloc ( g+1,sizeof * e); n = calloc (g + 1 ,sizeof *n); if (!e || ! + n) return E ( Z (memory error)) ; V=U+1; Y = y[-2] / 2; X = *y / 2; D = 1 + V; attron(A_BOLD) + ; curs_set(0);nonl (); intrflush(v,0 ); keypad(v, 1); noecho(); cbreak() ;start_color();init_pair + + ( 1, WALL , WB ) ; init_pair(2,HEAD, HB); init_pair(3 , BODY, BS); init_pair(4, BG, BB); S(0); B(0);x: + if (Q) + #undef d + + goto y ; x = *y ; getmaxyx(v,1[y],y [ - 1 ] ); C(1,1 ); mvhline(1,0,'#' ,y[-2]); mvvline(1,0,'#' + ,*y); mvhline(*y,0 , '#' , y [ -2]); mvvline(1,y[-2], '#',*y);C(4,1);q*U ,*V,'*');C(4,0);(*H)(0); + refresh(); timeout ( y [ - 3 ] ) ; switch (getch() ){ case KEY_LEFT:V [ 1 ] = l - 3 ; break; + case KEY_RIGHT: V[ l/l] = l/2; break ; case KEY_UP:V[ l-3] = l-1; break; case KEY_DOWN: V[l/4]=l; + break; case 'q': case'Q':Q=l; case ' ':(!P && (P =1 ))||(P=0); default :x = 0; } if(x) P=!*y;if + + + (Q||P)goto x; if(! Q && ! 1[V]) goto x; switch (1[V]) { case 1:--Y;break ; case 2 : ++ Y; break + ; case 3: -- X; break; case 4:++ X; break; } if ( Y <1 || Y >= y[-2] || X < 2 || X >= *y || + y[-2] >= y[-1] ||* y >= 1[y]) { if ( *p && !(*y>=1[y] ||y[-2]>=y[-1])) { if (Y<1||Y >= y[-2]) Y = + Y<1?y[-2]-1:1; if( X<2||X>=*y) X = X <2 ? * y -1:2; } else<% E(Z(OUCH!)) ; goto y; } } for (I = 0 + ; !4[p] && I < A; ++I) if (Y == e[I ] && X == n[I]){ E(Z(OW!)); goto y; } if (Y == *V && X == *U + )B(1); else { if( W&& !(++1[p] % W) ) H[2](0); if (3 [p]) { if (!(++p[2 ] % 3[p])) { H[1](G); 2[ + p]=0; } else S(0); } else S (0); } goto x; y:E(NULL ); printf(J free(e ); free(n); return 0; } diff --git a/ioccc/2020/ferguson1/prog.c b/ioccc/2020/ferguson1/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..ef3e27152bfbed2d3370b7b25400851cd9de8419 --- /dev/null +++ b/ioccc/2020/ferguson1/prog.c @@ -0,0 +1,53 @@ + #define d =strtoul(z,NULL,0)); + #define m(n) COLOR_%:%:n + #define v stdscr + + #define q mvaddch( + #define Z(x) %:x + #define F(x)z=getenv(Z(x)); z&&( + #define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n),Y,y[-2],X, *y, A, g, c ); + #include <curses.h> + + #include <unistd.h> + #include <time.h> + #include <stdlib.h> + + typedef size_t a; typedef unsigned long k; static a g= 997,c,A=5,I,N=5 ,G=5; static k p <:5:>= + <% 1 %>,W = 300; static int Y,X,*j =(int<:8])<% 231 %>,*U, *V,*e,*n, Q ,P,x,*y,l=4, * D; static + void b(a h) { c+=h ; mvprintw(0, 0,J } static int E( const char * L)<% static int h; !h&&endwin + (); h=l; L&&puts(L ); return 1; } static void C ( int L, int h) { attroff(m(PAIR(L))); h&& + attron(m(PAIR(L))) ; } static int R (int h, int L) { return (rand () % (L - h + 1))+h; } static + void S(a o){static const char*s =Z( ; +<>^v); q n[0] ,e[0],' '); A = f( A+o,g ); if (A >= g) { + E(Z(YOU WIN!)); Q = l; return; } C( 3, 1); for (I = 0; A && I < A - 1 ; ++I) { I && q n[I], e[ + I], 'o'); e[I] = e [I + 1]; n[I] =n[ I+1]; } A > 1 && q n[I],e[I], 'o'); e[I] = Y; n[I]= X; while + (++I < g) e[I] = n [I] = 0; C(2, 1); q X,Y,s[*D+2& (1 <<3)-!Q]); }static void B(a o){ if (o) { S( + N); b(1); } if (Q) return; p[1] = 0; !o && q*U,*V,' ' ); x: y[3] = R(1,y [-2]-1); y[2] = R(2,*y-1 + ); for (I = 0; I < A; ++I) if (*V == e[I] && *U == n[ I]) goto x; } int main(void) { char *z; y= + + + j+3; void (*H[])(a )={b,S,B} ; srand ((unsigned)time( NULL));if(!initscr ( ) ) return puts (Z ( + curses error) ) ; getmaxyx(v, *y, y [-2]); --*y; --y [-2]; if(y[-2]<9|| * y < 9 ) return E (Z + (screen too small) ); F(MAXSIZE)g d g = f((a)((*y-2) *(y[-2]-2)),g); F( GROW)N d F (SIZE) A d F + (WAIT)y [-3]=(int) strtol(z,NULL,0)) ; F(EVADE)W d U= y+2; F(WALLS) *p d F(CANNIBAL)p[4] d F(SHED + ) p[3] d F (SHEDS )G d e = calloc ( g+1,sizeof * e); n = calloc (g + 1 ,sizeof *n); if (!e || ! + n) return E ( Z (memory error)) ; V=U+1; Y = y[-2] / 2; X = *y / 2; D = 1 + V; attron(A_BOLD) + ; curs_set(0);nonl (); intrflush(v,0 ); keypad(v, 1); noecho(); cbreak() ;start_color();init_pair + + ( 1, WALL , WB ) ; init_pair(2,HEAD, HB); init_pair(3 , BODY, BS); S(0); B(0); x: if (Q) + + #undef d + + goto y ; x = *y ; getmaxyx(v,1[y],y [ - 1 ] ); C(1,1 ); mvhline(1,0,'#' ,y[-2]); mvvline(1,0,'#' + ,*y); mvhline(*y,0 , '#' , y [ -2]); mvvline(1,y[-2], '#', *y); C(1,0) ; q *U,*V,'*'); (*H) (0); + refresh(); timeout ( y [ - 3 ] ) ; switch (getch() ){ case KEY_LEFT:V [ 1 ] = l - 3 ; break; + case KEY_RIGHT: V[ l/l] = l/2; break ; case KEY_UP:V[ l-3] = l-1; break; case KEY_DOWN: V[l/4]=l; + break; case 'q': case'Q':Q=l; case ' ':(!P && (P =1 ))||(P=0); default :x = 0; } if(x) P=!*y;if + + + (Q||P)goto x; if(! Q && ! 1[V]) goto x; switch (1[V]) { case 1:--Y;break ; case 2 : ++ Y; break + ; case 3: -- X; break; case 4:++ X; break; } if ( Y <1 || Y >= y[-2] || X < 2 || X >= *y || + y[-2] >= y[-1] ||* y >= 1[y]) { if ( *p && !(*y>=1[y] ||y[-2]>=y[-1])) { if (Y<1||Y >= y[-2]) Y = + Y<1?y[-2]-1:1; if( X<2||X>=*y) X = X <2 ? * y -1:2; } else<% E(Z(OUCH!)) ; goto y; } } for (I = 0 + ; !4[p] && I < A; ++I) if (Y == e[I ] && X == n[I]){ E(Z(OW!)); goto y; } if (Y == *V && X == *U + )B(1); else { if( W&& !(++1[p] % W) ) H[2](0); if (3 [p]) { if (!(++p[2 ] % 3[p])) { H[1](G); 2[ + p]=0; } else S(0); } else S (0); } goto x; y:E(NULL ); printf(J free(e ); free(n); return 0; } diff --git a/ioccc/2020/ferguson1/snake-colours.sh b/ioccc/2020/ferguson1/snake-colours.sh new file mode 100644 index 0000000000000000000000000000000000000000..1d8bd90d54e0f6906def4db9917094347f2a7b8b --- /dev/null +++ b/ioccc/2020/ferguson1/snake-colours.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# +# Snake script that prompts for the colours desired for the colours for the +# walls, the head and body of the snake and the bug, and then proceeds to +# compile Snake with that profile and then start the game. If there's an input +# error it uses the default colour for the specific item. +# +# I don't disable any colours in the script even those that will probably be +# hard to see; interestingly although maybe not as easy to see black on black is +# not impossible to see. It's more like a grey on black. White background will +# probably be a problem but then again maybe not. +# +# Usage: +# +# [VAR=VAL ...] ./snake-colours +# +# Examples: +# +# WALLS=0 ./snake-colours +# ./snake-colours +# +# Why did I choose the colours I did? Because there are snakes with red heads +# and although the one I am aware of has a blue body it's easier to see (for my +# eyes at least) the green. At first I had red bugs but I thought white is +# easier to see and the red head with a green body also easier to see. +# Unfortunately blue on black doesn't turn out so great and the cyan for the +# snake body with a different colour for the wall didn't quite do it for me. But +# I explain how you can change these anyway. Anyway I love redheads and the +# snake in question Red-headed krait +# (https://en.wikipedia.org/wiki/Red-headed_krait) is stunningly beautiful too. +# +# Last updated: 13 May 2020 +COLOUR[0]="BLACK" +COLOUR[1]="RED" +COLOUR[2]="GREEN" +COLOUR[3]="YELLOW" +COLOUR[4]="BLUE" +COLOUR[5]="MAGENTA" +COLOUR[6]="CYAN" +COLOUR[7]="WHITE" +DFLT[0]="-DWALL=COLOR_CYAN" # Wall foreground: cyan (WALL) +DFLT[1]="-DWB=COLOR_BLACK" # Wall background: black (WB) +DFLT[2]="-DHEAD=COLOR_RED" # Head foreground: red (HEAD) +DFLT[3]="-DHB=COLOR_BLACK" # Head background: black (HB) +DFLT[4]="-DBODY=COLOR_GREEN" # Body foreground: green (BODY) +DFLT[5]="-DBS=COLOR_BLACK" # Body background: black (BS) +DFLT[6]="-DBG=COLOR_WHITE" # Bug foreground: white (BG) +DFLT[7]="-DBB=COLOR_BLACK" # Bug background: black (BB) +COLOURS[0]="-DWALL=COLOR_" +COLOURS[1]="-DWB=COLOR_" +COLOURS[2]="-DHEAD=COLOR_" +COLOURS[3]="-DHB=COLOR_" +COLOURS[4]="-DBODY=COLOR_" +COLOURS[5]="-DBS=COLOR_" +COLOURS[6]="-DBG=COLOR_" +COLOURS[7]="-DBB=COLOR_" + +function show_colours() +{ + echo "Colour selection for ${*} (enter for default)" + for i in 0 1 2 3 4 5 6 7; do + printf "(%d) %s\n" "${i}" "${COLOUR[${i}]}" + done + read -rp "Make selection (1 - 7): " colour + + case "${colour}" in + 0|1|2|3|4|5|6|7) + return "${colour}" + ;; + *) + return 255 + ;; + esac +} +function configure_colours() +{ + j=0 + for i in "WALL" "WALL (BACKGROUND)" "HEAD" "HEAD (BACKGROUND)" "BODY" "BODY (BACKGROUND)" "BUG" "BUG (BACKGROUND)"; do + show_colours "${i}" + x="${?}" + if [ "${x}" != 255 ]; then + COLOURS[$j]="${COLOURS[$j]}${COLOUR[$x]}" + else + COLOURS[$j]=${DFLT[$j]} + fi + j=$j+1 + done + + echo cc -o prog.alt prog.alt.c -D'f(a,b)'='((a)<(b)?(a):(b))' ${COLOURS[0]} ${COLOURS[1]} \ + ${COLOURS[2]} ${COLOURS[3]} ${COLOURS[4]} ${COLOURS[5]} ${COLOURS[6]} ${COLOURS[7]} -lncurses + + cc -o prog.alt prog.alt.c -D'f(a,b)'='((a)<(b)?(a):(b))' ${COLOURS[0]} ${COLOURS[1]} \ + ${COLOURS[2]} ${COLOURS[3]} ${COLOURS[4]} ${COLOURS[5]} ${COLOURS[6]} ${COLOURS[7]} -lncurses || exit 1 +} + +make + +./termcaps +T="${?}" +if [ "${T}" -ne 0 ]; then + read -rp "Terminal issues detected; do you wish to continue anyway (Y/N) ? " ans + [[ "${ans}" != "y" ]] && [[ "${ans}" != "Y" ]] && exit 1 +fi + +configure_colours + +clear && ./prog.alt diff --git a/ioccc/2020/ferguson1/snake.1 b/ioccc/2020/ferguson1/snake.1 new file mode 100644 index 0000000000000000000000000000000000000000..cb6d176c19323bb7dadfc2a44a3c3648e8ffd484 --- /dev/null +++ b/ioccc/2020/ferguson1/snake.1 @@ -0,0 +1,303 @@ +.TH snake 1 "11 August 2020" "snake" "IOCCC 2020" +.SH NAME +snake \- Feature\-rich curses implementation of the classic 'Snake' game with many gameplay modes and options for IOCCC 2020 +.SH SYNOPSIS +\fBsnake\fP +.SH DESCRIPTION +\fBsnake\fP has two cheat modes (passable walls/self[cannibalism]), a drawing/practising mode, \fIcan play by itself\fP (\fBand win!\fP), is coloured (included \fIsnake-colours.sh\fP and \fIplay.sh\fP scripts compile in player\-selected colours) and there are many other play modes (many more can be devised with the imagination and the environmental variables; see \fbENVIRONMENT\fP and the file \fIgameplay.markdown\fP for many examples) and options. +You can pause and there's even a built\-in test unit for some features! +Some of the configurable features are: +.PP +.RS +\fB\-\fP The speed of the snake (how many milliseconds to \fBWAIT\fP for input before moving; \fIdefault 231 milliseconds\fP and you can move faster by pressing the direction key quicker or or even holding it down). +.RE +.PP +.RS +\fB\-\fP If the bug (to eat) will move (\fBEVADE\fP) after user\-specified number of snake moves (\fIdefault 300, 0 disables\fP). +.RE +.PP +.RS +\fB\-\fP If the snake can go through \fBWALLS\fP (coming out at the opposite wall) (\fIdefault 1, yes\fP). +.RE +.PP +.RS +\fB\-\fP If the snake can go through itself (\fBCANNIBAL\fP) (\fIdefault 0, no\fP). +.RE +.PP +.RS +\fB\-\fP The initial \fBSIZE\fP of the snake (\fIdefault 5\fP). +.RE +.PP +.RS +\fB\-\fP The size the snake must become in order to win the game (\fBMAXSIZE\fP, \fIdefault 997\fP). +.RE +.PP +.RS +\fB\-\fP How much to \fBGROW\fP each time a bug is eaten (\fIdefault 5\fP, can be negative). +.RE +.PP +.RS +\fB\-\fP How many moves (\fBSHED\fP, \fIdefault 0, disabled\fP) before 'stretching' (grow) (\fBSHEDS\fP, \fIdefault 5\fP; can be negative). +This is how snakes grow in the wild so is a misnomer here because snakes don't grow in the manner that the original Snake game was designed. +.RS +\fB\- Exception\fP: If the bug is eaten the counter isn't incremented. +.RE +.RE +.PP +.RS +\fB\-\fP A drawing mode (\fBWAIT < 0\fP makes \fBtimeout()\fP set blocking read). +.RE +.PP +.RS +\fB\-\fP Computer plays the game (\fBWAIT=0\fP) +\fB(EPILEPSY/STIMULATION OVERLOAD TRIGGER WARNING\fP included in the relevant section of the \fIgameplay.markdown\fP; this goes for low \fBEVADE\fP values too). +.RE +.PP +.RS +\fB\-\fP Grow\-Shrink (Positive and Negative Winning) mode (see \fIgameplay.markdown\fP for more details). +.RE +.PP +.RS +\fB\-\fP The dimensions of the game (this is actually a terminal thing but I document how to do this and its potential pitfalls) (\fBLINES\fP, \fBCOLUMNS\fP). +.RE +.PP +.RS +\fB\-\fP Different colours and characters for the bug, snake head, snake and walls: +.RS +\fB\-\fP Bug is \fB*\fP (white). +.RE +.RS +\fB\-\fP Head is an arrow facing the direction the snake is facing (\fB<\fP, \fB^\fP, \fB>\fP, \fBv\fP) (red). +.RE +.RS +\fB\-\fP Body is \fBo\fP (green). +.RE +.RS +\fB\-\fP Walls are \fB#\fP (cyan). +.RE +.RE +.SH OPTIONS +.PP +The options are specified via the environmental variables. +.SH ENVIRONMENT +The following environmental variables modify the behaviour of the game: +.PP +\fBGROW\fP +.RS +How much to grow each time a bug is eaten. +Negative growth is a different gameplay mode. +\fIDefault 5\fP. +.RE +\fBSIZE\fP +.RS +The initial size of the snake. +\fIDefault 5\fP. +.RE +\fBMAXSIZE\fP +.RS +The max snake size (the size the snake must become to win). +\fIDefault 997\fP. +Limits are always imposed depending on the size of the terminal. +Negative number sets to max size based on terminal size. +.RE +\fBWAIT\fP +.RS +The number of milliseconds to wait for input (how fast the snake moves). +\fIDefault 231\fP. +\fI0\fP has no delay: the computer will play by itself (though you can still change directions). +\fI< 0\fP is drawing mode (makes \fIgetch()\fP block). +.RE +\fBEVADE\fP +.RS +The number of movements before the bug tries to move to a new place (evading the snake). +\fIDefault 300\fP (0 disables). +.RE +\fBWALLS\fP +.RS +Whether the snake can go through walls. +\fIDefault 1\fP (yes). +.RE +\fBCANNIBAL\fP +.RS +Whether the snake can go through itself. +\fIDefault 0\fP (no). +.RE +\fBSHED\fP +.RS +How many moves before the snake 'moults' (shedding of skin to make room for growth). +Again this isn't technically accurate in Snake. +\fIDefault 0\fP (disabled). +.RE +\fBSHEDS\fP +.RS +The amount to grow by each time the snake sheds its skin. +\fIDefault 5\fP. +.RE +.PP +The following two modify the terminal dimensions (this is not part of the game but the terminal/curses itself): +.PP +\fBLINES\fP +.RS +The number of rows. +Default is the maximum size of the current terminal size (\fBecho $LINES\fP will show the current value). +Please note that this is not the number of playable rows but the entire game itself. +.RE +\fBCOLUMNS\fP +.RS +The number of columns. +Default is the maximum size of the current terminal size (\fBecho $COLUMNS\fP will show the current value). +Please note that this is not be the number of playable columns but the entire game itself. +.RE +.SH FILES +The markdown files have html counterparts; for some of these the html version is probably easier to read and make use of. +.RS +\fIprog.c\fP +.RS +Source file to the Snake game (IOCCC entry source file). +.RE +\fIremarks.markdown\fP +.RS +Describes what the entry (game) is, what it looks like, how to play etc. +Includes a variety of other information as well as NAQs (never asked questions that I believe could actually be asked so perhaps better would be infrequently asked questions, IAQs). +.RE +\fIgameplay.markdown\fP +.RS +Includes information on how to play, demonstrates some of the features and describes many gameplay modes. +.RE +\fItroubleshooting.markdown\fP +.RS +Information to help work out any possible problems as well as show how to configure and restore terminal dimensions for the game. +.RE +\fIterminals.markdown\fP +.RS +A troubleshooting guide focusing more on terminals. +.RE +\fICOMPILING\fP +.RS +Information on Portability, C standards as well as (for the IOCCC judges) both Justifications for certain things and lints. +.RE +\fIHACKING\fP +.RS +Documentation on how to modify the input keys, colours, wall, bug and snake chars (to print), the status/score line and various other things. +Includes feature ideas as well as how one might implement them. +.RE +\fIspoilers.markdown\fP +.RS +Technical details that give more away about how the program works (\fIHACKING\fP also does a bit of this). +.RE +\fIMakefile\fP +.RS +To build the terminal capabilities test utility and the Snake game itself. +.RE +\fIsnake-colours\fP +.RS +Helper script to compile the game with player selected colours. +.RE +\fIbugs.markdown\fP +.RS +List of bugs and things that might appear to be bugs that aren't, were once bugs etc. +.RE +\fIchocolate\-cake.markdown\fP +.RS +The judges love chocolate and who can blame them? This is something of a speciality of my mum's but it's a delicious cake that even my late stepmum (who only liked white chocolate) loved! Double\-layer chocolate fudge cake. +.RE +\fItermcaps.c\fP +.RS +Source file to test terminal support for the used capabilities the Snake game uses. +.RE +\fIsnake.1\fP +.RS +See this file to see the manual i.e. this file. +Don't get lost in the snake pit! +.RE +\fIcannibalism.log\fP +.RS +A screen dump of what cannibalism can look like right before winning. +.RE +\fIcrazy.log\fP +.RS +A screen dump of the positive/push - negative/shrink mode. +.RE +\fIplay.sh\fP +.RS +Script that prompts if you want to reconfigure colours and then gives you a menu that runs some preconfigured game modes. +This script essentially combines \fIsnake-colours\fP with some preset modes that you can select from a menu. +.RE +\fIprog.2.c\fP, \fIprog.3.c\fP, \fIprog.3-j.c\fP, \fIprog.alt.c\fP +.RS +Other versions I submitted. \fIprog.2.c\fP is the second version; \fIprog.3.c\fP and \fIprog.3-j.c\fP were the third where the \fI-j\fP version was a minor change to the J define. +\fIprog.alt.c\fP is the file that has support for colour customisation of the bug (this would have broken rule 2a/b so I could not submit it as my primary version). +It also clears the screen before playing to try and maintain terminal sanity should you pass the LINES environmental variable to the program. +.RE +.RE +.SH BUGS +.RS +\fB\-\fP The screen keeps showing bugs! +.RE +.RS +\fB-\fP There's no boss screen. +.RE +.RS +\fB\-\fP It was written by a human being. +.RE +.RS +\fB\-\fP Technically walls, snakeskin and the snake itself would \fBnot\fP be an obstacle in real life. +The shed snakeskin is not an obstacle but walls can be and so can the snake itself. +Also snakes grow by moulting (technical term for shedding) so when the snake leaves its snakeskin behind it really ought to grow but instead it shrinks; this means negative shedding ought to have the snake grow and positive shedding have the snake - what? +It's a misnomer: it took fewer bytes and the negative shedding is a positive consequence of unsigned arithmetic. +.RE +.PP +On a more serious note see the \fBbugs.markdown\fP file. +.SH EXAMPLES +.PP +Test your terminal capabilities and get other various data (based on dimensions of terminal, growth size, size and max size as specified i.e. you can pass in the variables \fBLINES\fP, \fBCOLUMNS\fP, \fBMAXSIZE\fP, \fBGROW\fP and \fBSIZE\fp): +.nf +.RS +\fB + make test\fP +.fi +.RE +.PP +This is imperfect! +.PP +Allow the snake to go through itself but not through walls, make the snake move at 400ms and start out at size 7: +.nf +.RS +\fB + CANNIBAL=1 WALLS=0 WAIT=400 SIZE=7 ./snake\fP +.fi +.RE +.PP +Let the snake go through itself and the walls, make the bug stay put until it's eaten, have the snake grow by 7 every 150 snake movements, start out at size 4 and grow by 7 every time a bug is eaten: +.PP +.RS +.nf + \fBCANNIBAL=1 WALLS=1 EVADE=0 SHED=150 SHEDS=7 SIZE=4 GROW=7 ./snake\fP +.fi +.RE +.PP +Allow the game to play by itself, winning, after starting the game (move in a direction) (\fBDON'T TRY IF YOU HAVE EPILEPSY!\fP): +.nf +.RS +\fB + CANNIBAL=1 WAIT=0 MAXSIZE=30 SIZE=0 EVADE=1\fP ./snake +.fi +.RE +.PP +That allows the snake to go through itself, makes the max size fairly small (to make it easier to win and quicker), sets the size to 0 (start with only the head) and make the bug move every time the snake moves (and does not catch it). Once you move the snake a direction it moves so quickly that because the bug is evading the snake inevitably runs into the bug thus growing in size etc. +.PP +Run script that prompts for the colours to be used, compiles and then runs the game (with environmental variables passed in): +.nf +.RS + \fBCANNIBAL=1 SIZE=15 MAXSIZE=45 WALLS=0 ./snake-colours\fI +.fi +.RE +.PP +That will compile the game to be the colours you select and then enable cannibalism, set the starting size to 15, max size to 45 and walls are made impassable. +.PP +For more gameplay information and modes check \fIgameplay.markdown\fP; and for an interactive script that prompts for some of those modes see the \fIplay.sh\fP script. +.SH AUTHOR +Written by Cody Boone Ferguson for IOCCC 2020 (the 27th IOCCC). +.SH SEE ALSO +.PP +\fB\<https://ioccc.xexyl.net/2020/snake\>\fP The 27th IOCCC 'Don't tread on me award'. diff --git a/ioccc/2020/ferguson1/spoilers.text b/ioccc/2020/ferguson1/spoilers.text new file mode 100644 index 0000000000000000000000000000000000000000..c25c386d2606d56c6270d13ca329be61869be557 --- /dev/null +++ b/ioccc/2020/ferguson1/spoilers.text @@ -0,0 +1,941 @@ +# Introduction (SPOILER ALERT) + +In the [gameplay.markdown][] ([gameplay.html][]) file I have given enough +information to know how the game looks, how to move the snake, how to pause etc. +In this file I am including (some) information on how the game actually works: +the technical details as it were, obfuscation techniques and also some of the +ways I reduced the iocccsize so I could do more with the code. Probably this +file causes more spoilage than the other files though that's not to say +everything will be answered here. + +If you're still interested in this file (i.e. you're a judge or someone who +wants to know more about it) read on. Yes I write a lot. But you probably +already knew that so no harm there, hey? + +<a name="toc"></a> +- [How does it work?](#works) +- [How does the snake movement work?](#movement) +- [Drawing (manual) and computer playing (automatic) modes](#manual-automatic) +- [Collision detection](#collision) + * [Cannibal collision detection](#cannibalcollision) + * [Collision detection when resizing the window of the game](#resizing) +- [Obfuscation](#obfuscation) +- [Skinning the snake (i.e. decreasing the iocccsize)](#skinning) +- [A few more interesting size optimisations](#size) + +# <a name="works" href="#toc">How does it work?</a> + +The gameplay I have already described but this explains the way things are +actually done in more detail. + +First I initialise curses; if this fails I print an error message ('curses +error') and return 1. Next the screen size is determined and I subtract 1 from +each the x/y. If it's too small curses is ended and an error message ('screen +too small') is printed - returning 1. + +Next the max size of the snake is determined: if `MAXSIZE` is specified then +it's the value of that; otherwise it's the default. But in either case if it's +too big based on the screen dimensions it's capsized. The arrays for the snake +are this size + 1. Other environmental variables are also processed. + +Then the arrays are allocated; if either return NULL curses is ended, an error +message ('memory error') is printed and return 1. + +If no errors have occurred I set up colours, turn on bold, set up the keypad +etc., place the snake, the bug, draw the walls and then it waits for the first +move (or quit of course). Technically I don't 'wait' for input as such: unless +the wait time is negative (drawing mode) it's just a non-blocking call up to the +WAIT milliseconds but in no event will the snake move until it is told to at +least once (in drawing mode it will always wait). + +In drawing mode if you pause then when you resume (hit space) the snake will +move the last direction it had been told to move - because the direction is set +and input was detected (the same goes for another key e.g. 'g' - just like in +normal mode). But it will then wait again for input. + +The snake function both draws the snake and updates the arrays; if the new size +is >= the max size the game is won (the winning size will be shown as the max). + +Else the arrays are updated; when the array is being updated the body of the +snake is drawn. After this the head is drawn. Depending on the length of the +snake wrt the size the snake technically it might be that the number of +characters the snake takes is increased rather than having moved the snake +forward (i.e. the tail moved by one). This registers where the snake is and +where it was but no longer is (important particularly for negative growth/shed +sizes). + +After that a bug is placed (but not drawn) in a pseudo-randomly selected area of +the field. This function takes a parameter which if not 0 and the bug had +already been placed somewhere (in other words if the bug was just eaten) call +the snake function. As long as the game isn't won at that point find a new place +to place the bug. + +Next the score line is updated and then whilst the game is not over (player +loses/quits/wins) the movement proceeds; if the game hasn't started yet it will +jump to the top of the loop. If it's paused the same thing until it's resumed. +The rest of the loop can be described thusly. + +It checks the current max y/x, draws the walls, bug, gets any input from +keyboard, and then if there is movement checks for collisions; if current max +x/y are is/are smaller than original then it's automatically a game over from +running into walls regardless of that feature status - this simplifies things +greatly (see below for more details). + +If cannibal mode is disabled (the default) and the snake runs into itself then +it's also game over. Or did it run into the wall? If walls are passable (the +default) it will come out from the other side; else it's game over. If it comes +out on the other side and the snake is there and cannibal mode is disabled then +it's also game over. + +As the snake moves it will for each move grow by one up to the technical size. +This might at times look a bit different from other times but it's a visual +thing based on the internal data of the game and the features enabled for +example shedding and shedding size. + +Finally if the snake's new coordinates are on a bug a new bug is placed on the +field, the snake grows and the score is updated. Otherwise if the bug has waited +the number of moves that it waits before it finds a new place the bug is placed +in another location too (and the snake does not grow). In either event the snake +location is updated and redrawn. + +There's also the processing of any shedding at this point. If the snake eats a +bug the snake will not shed; if it sheds the snake will not move in the same +manner as if it simply moved. Growth/movement can in some ways be conflated. + + +# <a name="movement" href="#toc">How does the snake movement work?</a> + +The way the snake looks to move is that every time the snake moves the last +position (the tail) is replaced with a space (`' '`). If the snake eats a bug +then the snake will get bigger in the next `N` movements. Note that if the snake +isn't its full size it will only be growing and so might not appear to be +moving at the tail end; I have discussed this more than enough elsewhere. + +There are two arrays that store the last Y/X coordinates of the snake's +positions that are shifted forward as the snake moves about the field looking +for bugs. + + +# <a name="manual-automatic" href="#toc">Drawing (manual) and computer playing (automatic) modes</a> + +How do these modes work? The `timeout()` function takes a signed int: if it's < +0 it waits indefinitely; if it's 0 it returns immediately even if there's no +input waiting (if input is there then it's used instead); and if it's > 0 it +waits that many milliseconds. Thus a negative value allows for complete control +over the snake's movement (speed and otherwise), a value of 0 means the snake +will move as long as it's not paused etc. and otherwise it waits up to that many +milliseconds (which is how the 0 value comes into play). + + +# <a name="collision" href="#toc">Collision detection</a> + +This was an interesting thing to work out. Because the snake could occupy more +than one row and more than one column at a time the two arrays approach seemed +good to me. + +I already mentioned how the array is shifted but to be clear: the snake head is +always at element size - 1 and the tail is at 0 and so it's just a matter of +verifying if the snake head is at a place that's occupied by the snake, the wall +or the bug. + +The bug does its best to avoid landing where the snake is but given that snakes +are very flexible and cunning who can tell what might happen? As I noted these +bugs are not bugs! :) + + +## <a name="cannibalcollision" href="#toc">Cannibal collision detection</a> + +How does cannibalism change collision detection? The fact that each time the +snake function is called there is a space printed at the tail end was a problem +to resolve: what happened is if the snake went through itself then at some point +there would be a space that breaks the snake into more than one piece (where the +tail was but that had been another part of the snake)! + +So what I do: first the tail is cleared, then as the snake coordinates arrays is +being updated I redraw the snake chars. Then at the end the head is drawn (it +used to be the head was drawn first but by drawing it after you can see where +the head is inside itself, creepy as it is). Thinking on it this very possibly +is why (or partly) the negative shedding leaves the head somewhere in the middle +of the snake (or that the head of the snake is left behind) but again I don't +think that as a problem. + +There are other strange ways this looks. Not only does it look like lines +intersecting at any number of places but it looks particularly strange when the +snake goes the opposite direction: it has to unwind as it were, and for a moment +you might not see what is truly happening. There are two ways you can look at +this I think. + +First is that it's physically impossible in real life so the fact this cheat +mode exists for a different kind of play means it should look unnatural: for it +*is* unnatural! + +The second is you can look at it as if two more snakes are having fun with each +other. This can also appear to defy physics! + +Choose your poison. Or rather your venom. + + +## <a name="resizing" href="#toc">Collision detection when resizing the window of the game</a> + +What happens if the window is resized during the game? If the size is increased +then the border can (and will) stay the same; but if the window is shrunk then +what? It would be very difficult if not impossible to redraw the snake: where +would the snake be and what about the border? The arrays would have to be +adjusted too! Another issue: what if the snake is beyond the new walls? + +The best thing I could think of is that if the window is shrunk then the snake +is assumed to run into the wall: in other words the game is at that point over. +If the window is increased in size nothing happens other than the game won't be +the full window size (or technically a few rows/columns fewer): everything will +remain the same. This GREATLY simplified things. + +There was another problem at some point where the snake would quickly grow if it +was increased in size but I believe that's resolved. Anyway what kind of field +in real life increases in size like that so suddenly? :) + + +# <a name="obfuscation" href="#toc">Obfuscation</a> + + +- I make use of the C token pasting operator. Although this is well known it's +probably less known and either way it's not as simple as just having the code +that it translates to. For example why have: + + attroff(COLOR_PAIR(L)); + + When you can have instead: + + attroff(m(PAIR(L))); + + It's an extra layer of indirection. This used to be more used but when + making it easier for users to change the colour pairs I no longer used it to + set up colour pairs. It might not defeat `cpp` but it does make for more + reading otherwise (depending on how you look at it maybe less?). + + It also helps save iocccsize bytes (but not as many as it used to!). + + +- What is this block of code? + + F(MAXSIZE)g d g = f((a)((*y-2)*(y[-2]-2)),g); + F(GROW)N d + F(SIZE)A d + F(WAIT)y[-3] = (int) strtol(z,NULL,0)); + F(EVADE)W d + /* and so on */ + + There are several things going on here but I'll focus on the main one here and + leave the others to their own: the `F` macro and the associated `d` macro are + here important. + + In addition to saving many bytes this also makes for interesting reading. + What this actually is doing is checking for environmental variables. If + `getenv()` does not return NULL then strtoul() is called on it (except for + the one that clearly shows strtol()). + + There are other things going on (below). + + Now it might not defeat the cpp but can you tell me what this is even with the + cpp? + + f((a)((*y-2)*(y[-2]-2)),g); + + The cpp might get it closer to what you might expect in a normal program but I + refer to the array offsets (below also). + +- Stringification: there isn't a single `"` in the source code! The `F` macro +uses the macro `Z` which does the real work. At first `F` was only `getenv` but +I changed it to use stringification. Following the creation of the `Z` macro I +made it use it instead. If I remember rightly that uses extra bytes but somehow +it felt better this way in my head. Then to save many bytes I made the macro do +much more than that (that is the `F` macro). + + As for the Z() macro it means that I could remove `"`s; for example: + + #define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n), Y, y[-2], X,*y,A,g, c); + + Which as I have discussed elsewhere is the entire set of parameters to both +`mvprintw()` and `printf()` plus the end of the function call (i.e. `);`. + + BTW: There's another really cool benefit of stringification: because more than +one space is converted to a single space I can have it spread across columns on +the format and even new lines if necessary. This fact along with the next +technique causes some beautifiers problems too. + +- Another use of the `Z` macro is this curious line: + + static char s[]=Z(; +<>^v); + + There are a number of curious parts. First is the Z() part makes it look + like a function call. Of course that wouldn't work as such because an array + initialiser needs an initialiser list or a string literal. Whether that's + immediately obvious to others I don't know but then how is this even possible? + A `;` followed by ` `, `+`, `<`, `>`, `^`, `v`? + + A very minor factor is that the character 'v' is there and it's (`v`) also + used as a macro (well, define) 'might' be of something to some people. Or + programs maybe? For instance using in vim `*` on the `v` in that array and + it takes you other instances of `v`: as in `\<v\>`: which happens to be + something else entirely. That itself however might or might not be + significant for this instance! + + But what function would take the string (...function and string?) that it takes? + The sequence of characters would normally cause compiler errors like that. + I have it in the function that uses it; static since it need never change: + only one copy is needed. Why I have it in the function is to move it further + away from the definition of `Z()`. I will also be returning to this one + again. + + Another example is using the `E()` function e.g.: + + E(Z(YOU WIN!)); + + Which happens to be in the same function the above char array is defined. Also +it's more like a string than anything but yet it's not visibly a string. + + Some beautifiers don't like this. + +- There's an `#undef` following an `if` in a way to draw attention from what to +do if the if is true. + +- There are a couple case statements that fall through to the next case +condition. Actually one falls twice: into the one below which falls into the one +below that. This means the order it is in is required. It also reduces the +iocccsize a reasonable amount (by having it in the main loop I could do these +things which reduced the number of keywords needed). + + When quit is requested it falls into pause. But then pause falls into the + default (so no recognised key is pressed) which does `x = 0;`. Outside the + switch block there's `if (x) P = 0;`. So what this amounts to is: if quit + is requested pause will be changed to the opposite state. This will then + fall to setting x to 0. And because x is 0 the state of pause won't be + updated again. Now because `Q = 1;` (or actually `l`) it doesn't matter if + `P || !P` because Q will also jump to the top of the 'loop' only to exit + since the condition no longer is true. + + But then if pause is pressed the same thing applies: it will be updated to + the opposite state and then it will fall to the default case which sets `x = + 0;` which means it won't update pause outside the switch block. If pause was + enabled then the loop will start over only this time because quit wasn't + requested it will re-enter the loop. + + So basically quit can both pause and resume but it doesn't matter because it + will still quit; and pause will fall to the default statement without being + updated again either. In other words the only time pause will be updated + (disabled) *outside the switch* is if a direction key is pressed. But of + course it's disabled inside the switch if pause key is pressed when it's + already paused! This removed three break statements because the order allows + it; if the order was changed then the code would break in another way and + not the good kind! + + +- On the note of pausing there's at least one instance of removing `if..else` +(besides those in e.g. environmental variable processing) that's curious: I +converted this: + + if (!P) P = 1; + else P = 0; + + To this: + + (!P && (P = 1))||(P=0); + + +- Makes use of the different 'namespaces' to have variables and labels be the +same identifier. For example in main() there's a variable that also have the +same name label for `goto` (there used to be two pairs in main()). + +- And on that note: makes use of the ugly `goto` in numerous places. This +includes simulating a while() loop, breaking out of that 'loop', breaking out of +two loops (a for() in the 'while()'), re-entering (as in starting over) a for() +loop and for dealing with errors. + +- Why do I check for `Q || P` and then goto x only to then check for `!Q && !D` +to then goto x? Do I need to check Q at all? In fact I do but at a quick glance +it might be easy to miss. + +- Uses an unnamed array (compound literal) for several different game variables. +The pointer to the first element is defined like `int *j`: + + static int Y,X,*j = (int[8]){231,0}, *U, *V, *e, *n, Q, P,x,*y,l=4,*D; + + Does the 231 seem familiar? It should: it's the default key delay for the + `timeout()` call (which I will return to again). The rest are 0 default. But + what about `j`? Is it even used? Actually in main: + + y = j+3; + + But aside from that `j` is not used. However... + +- Major abuse of negative pointer offsets along with confusing names. I'll say +this in two parts: the negative offsets and then the confusing names. + + Can you honestly tell me that this is easy to follow? + + if (Y < 1 || Y >= y[-2] || X < 2 || X >= *y || y[-2] >= y[-1] || *y >= 1[y]) + { + if (*p && !(*y>=1[y]||y[-2]>=y[-1])) + { + if (Y<1||Y>=y[-2]) + Y = Y<1?y[-2]-1:1; + if (X<2||X>=*y) + X = X<2?*y-1:2; + } + /* ... */ + } + + That's not the only place negative offsets occur! Observe the ternary operators + there too. + + I'll go back to the F() macro and in particular what follows one of them: + + g d g = f((a)((*y-2)*(y[-2]-2)),g); + + To parse that at the very least you have to know that `y` points to `j + 3`. + Then you have to know that `j` points to the first element of an unnamed + array (compound literal). But then you also have to know that that array has + different types of data. Once you figure out the elements in question you + then have to account for the offset that `y` is. Then once you have that + figured out you need to consider the negative offsets to `y` (this also + applies to the block above of course and maybe more so). Then you have to + think of operator precedence etc. I mean what is: + + (*y-2) * (y[-2]-2]) + + ...about? An offset of -2 and subtract -2 from that. Multiply that by the `*y` + (which is `j[3]`) - 2. + + But why is there a `g d g =` when the other lines only have the variable (or + location) and a d? (Excepting the one that doesn't refer to `d`.) + +- On the confusing names etc.: the `getmaxyx()` function gets the maximum Y, X +dimensions. Now in the first call in main() I have the code and tests following: + + getmaxyx(v, *y, y[-2]); + --*y; --y[-2]; + if (y[-2] < 9 || *y < 9) + return E(Z(term too small)); + + Clearly the max x must be stored in `*y` and the max y must be stored in .. + `y[-2]`. After all anyone knows that the coordinates are in the order (X,Y)! + In fact the output of my entry and my documentation demonstrates this + clearly: X before Y! It's so true in fact that the documentation for curses + more than once states that it's actually (Y,X)! But the fact I don't even + refer to a `x` is possibly confusing even without the negative offset. + + Of course I don't have to use negative offsets at all! I could use positive + offsets for every time I use negative offsets. But where's the fun in that? + :) + + BTW: Some of these are not in the table of expressions in the HACKING file. + Also there might be some code in there that is no longer correct (it was + before I started obfuscation) though it might be able to give an idea. + Spoilers abound in that file (in addition to this file) but the HACKING file + states things that are no longer true: a way of obfuscation itself! Instead + of misleading comments it's misleading statements in the file that explains + what some of the things are for! + +- Misleading variable names for coordinates. In other words the Y coordinate is +called X and the X coordinate is called Y. This adds to the already confusing +array references but it also adds to the confusion of the order of the curses +functions coordinates: it appears that yes X does come first because the +function calls that take coordinates suggest it - but in actuality it's just +that the names are deliberately swapped. Of course that's after you determine +that the variables `X` and `Y` are only the snake head but at that point you +still have to figure out the array confusions. Also if you're tired `V` could +easily be read as `Y` and I have a lot of fun with `V` which I will get to next +(and again). Finally why not have them be two different names unrelated to +coordinates? I thought of this and I think it's more confusing to have something +that is associated to what it is but incorrectly rather than something unrelated +entirely: the mind constructs things from what it has seen, what it experiences, +what it knows, and since X and Y are used for coordinates the natural response +of the brain is to assume Y is what is really X and X is what is really Y. + + +- More confusion with variable names: If you notice the `int *U, *V` they are +also part of the compound literal: that is they point into it: + + U=y+2; V=U+1; + + Except that these two are done in two different places: away from the + assignment of `y` to remove them further away from the contexts they are + used in. + + There's another reason for moving it further down: if you look at the bug + drawing function (which comes before main()) you will see that there I set + the bug location to refer to the `y` 'array'. I do blank out the old + location at `*U, *V` but then assign the new location differently. Then in + main() I draw it at `*U, *V` and also check for the bug being eaten there + too. + + +- There's another array that holds a variety of data. + + static k p[5]={1,0},W=300; + + It holds the following information (but not necessarily in this order): + + WALLS + CANNIBAL + SHED + SHEDS + EVADE + + But how will you know that just looking at the declaration? Many variables + and they're part of collections but the many layers of indirection cause + confusion to the already unhelpful variable names (for those that even have + names!). + + +- There's an array of pointers to functions too: it holds three functions but +rather than always use the array I only do some of the times. I even use the +same function in the same general area with both names in order to mislead. +Incidentally `splint` seems to have a parse error on the declaration though I +don't know why. + + +- On arrays/pointers in general I also use e.g. `3[p]` and `p[3]` (there are +many other examples that I have already shown). + +- Expanding on referring to the same thing in more than one way take a look at: + + case KEY_LEFT: + V[1] = l-3; + break; + case KEY_RIGHT: + V[l/l] = l/2; + break; + case KEY_UP: + V[l-3] = l-1; + break; + case KEY_DOWN: + V[l/4] = l; + break; + + What's going on there? First of all the letter ell looks very much like the + digit one but above there are only two references to the digit `1`; the + others are the letter `l`. If you're tired though, don't have the best + vision (I'm speaking from experience here and that's not even considering + the font) it would be easy to miss. Online in a text editor you have syntax + highlighting of course but there's more to it than that. Also in other parts + of the code there are references to the digit 1 instead of the letter ell as + part of array indexes too (so which is it?). + + Second is that the index referenced in each of the case statements evaluate + to the same: 1. That's all accomplished by taking advantage of the value of + `l`: 4. + + And then to further make use I have done the same for the value to assign to + that element: 4 - 3 is 1, 4 / 2 is 2, 4 - 1 is 3 and 4 is obviously 4. + + But doing it this way means you have to first of all know that there's the + variable `l` (conveniently declared at the top of the file); then you have + to determine (once you're at this place in the code) if it's the digit or + the letter - for each reference (since both exist)! After all it's entirely + possible that I could have negative offsets here (and there's nothing that + would prevent negating a variable either in this case): I have done it many + other places! But even after all of that you still need to do the + calculations when I could simply have had: + + V[1] = 1; V[1] = 2; ... + + Etc. + +- Variable reuse. For example in the function E() there's a variable that keeps +track of whether or not it's been called; that variable is `h` and it says +whether to call `endwin()` or not in as in some cases E() is called more than +once. Now instead of setting the variable `h` to 1 I set it to `l`: it looks +like a 1 yes but it's actually 4. Does it matter that it's 4? No. The only +thing that matters is that it's a non-zero value. The same applies to `Q` which +I also set to `l`. + +* I also use `*y` as a boolean. If you observe that I set x to `*y` (which +itself might make one believe they're related in some form): it used to be just +a 1. However it is only used as a boolean. `*y` as I described as the LINES +variable on invocation of the program. Since I check if it's < 10 before +continuing the game I know that it will always be non-zero. But what if someone +tries LINES=0? In fact it will be ignored: if the terminal is 25 lines and you +specify 0 lines then it'll be 25. Therefore I can use it as a boolean here since +it needs there to be non-zero. Then in order to get the opposite, 0, I can do +`!*y` which I do elsewhere. + +- More generally on variable reuse: the compound literals and arrays of the same +data type but which are completely different things means I can use the same +name in different parts and so it's then a matter of determining which +element/offset to use. + +- Why do I compare if the original dimensions are >= the current when the idea +is to make sure that they're actually bigger? How does that work? Why not just +check if it's > than the current? + +- More confusion with the max x/y dimensions: Going back to max x/y dimensions +and coordinates of the snake; I showed this code before: + + if (Y < 1 || Y >= y[-2] || X < 2 || X >= *y || y[-2] >= y[-1] || *y >= 1[y]) + { + if (*p && !(*y>=1[y]||y[-2]>=y[-1])) + { + if (Y<1||Y>=y[-2]) + Y = Y<1?y[-2]-1:1; + if (X<2||X>=*y) + X = X<2?*y-1:2; + } + else + { + /* ... */ + } + } + + I asked if you could honestly figure that out easily. But here's a bit more + elaboration. I already talked about the negative offsets - and they should + talk enough themselves - but look at the mess. Even if they weren't negative + offsets there are a lot of array references (though by a pointer to an + element in the unnamed array) and comparisons all jumbled together. There's + more. + + I have the `!` of a `||` to flip the logic: that's not how a normal person + would write code. Well...not usually, I guess; I have done it in times where + it seems more appropriate but it's not the way it's usually done (I think?). + + Even so that part is doing more than one thing: Not only is that code making + sure the max dimensions aren't smaller (from the original) but it also makes + sure that the wall isn't hit (when it's not allowed) as well as making the + snake go through to the other side of the wall if the snake is allowed to + and hits the wall! And even when the snake is allowed to go through walls if + the screen size has shrunk it will reach the else part. + + It also has the ternary operator to adjust the coordinates of the snake head + should the snake go through a wall and those also have negative offsets. But + how can you figure that out just looking at that mess? Unhelpfully the X/Y + seem to both be compared to `y` but never `x` (that variable is unrelated + and not even in this part of the code). + + +- The function `B()` ends with a `goto`. Why? It's also another place where +there's at least one negative offset. + +- A note on the many `#define`s in my entry. You say you dislike them: + + Doing masses of #defines to obscure the source has become 'old'. We + tend to 'see thru' masses of #defines due to our pre-processor tests + that we apply. Simply abusing #defines or -Dfoo=bar won't go as far + as a program that is more well rounded in confusion. + + As I have noted though many of these save quite a lot of bytes too. It's + true that they might aid (but barely) in obfuscation but I think that my + entry is more rounded in confusion; certainly the other techniques I have + mentioned include much more than just `#define`s. One of the `#define`s that + saves a significant number of bytes is of course `J`: I use that twice and + it would be a huge burden to include it twice! + + At the same time I have removed some `#define`s that have added bytes; I've + also removed some that saved bytes and in fact I think it makes it more + obscure if in no other way but making it more difficult to look at (for + example I might have been able to save bytes by defining for the array + offsets but I find that it looks much better - which is to say much worse - + the way I have it now). + +- Going back to the curious `static char s[]=Z(; +<>^v);`: there's something +magical about the number 7 isn't there? I do not refer to primes although +certainly one could say that primes have a magic to them. No. I'm instead +referring to another property: bitwise AND. For example consider the following: + + 7 & 0 + 7 & 1 + 7 & 2 + 7 & 3 + 7 & 4 + 7 & 5 + 7 & 6 + 7 & 7 + + What is the result of each operation? Quite simply it's the number itself! + How does this relate to the `s` array though? Let me back up. Is there any + place in the code that has the number 7 (by itself - 997 doesn't count)? A + quick check will answer that: no. But here's a curious thing: + + q X, Y, s[*D+2&(1<<3)-!Q]); + + We KNOW that at this place `Q` is 0 so the `!Q` has to be 1. Now `1 << 3` is 8. Therefore + + (1 << 3) - !Q == 7 + + But what's `*D`? If the snake hasn't moved once yet it's 0; otherwise it's the number + of the direction the snake is currently facing. Thus + + *D&(1<<3)-!Q + + ...refers to `*D`. However if I were to have that be the element it wouldn't + work right: I wanted the semicolon in there but the space was needed to + reduce the iocccsize down by one (ironic that adding a byte reduces it by + one but there it is). I could have had it later in the array but this felt + slightly more confusing: more operators (so precedence) to consider (and in + fact GCC complains about this but as is clearly demonstrated it's not + important). By adding a `+2` it adjusts the index to be the correct value in + order to show the proper index of the char array. + + But how do you know this? You have to know first of all that Q will always + be 0 at this point (so therefore !Q == 1). You also have to understand that + in the range N = 0..7 the value of `N & 7` is `N` (which might not be + something everyone realises). Obviously you need to know that (1 << 3) is 8 + in order to get the final `*D & 7`. + + You furthermore need to know that `*D` will always be in the range `0..4` + which means that `*D & 7` will always be in the range `0..4` (If I were to + have added a `& 7` to the end it'd still be the correct value! But the use + of bytes couldn't be justified there.) Finally adding 2 will get the correct + value of the array index. After all that it will print the correct character + for the head! + + But there's another trick here: there's never a direct assignment to `*D`: + `D` is set to `1 + V` and `*D` is never touched directly: it's all through + `1[V]`. The references to directions i.e. `KEY_LEFT` etc. and also the + switch() to see how to modify X/Y are all done through the `V` pointer. But + then what is `V` anyway? It's `U + 1`; and `U` happens to be `y + 2`. But + `y` happens to be `j + 3`. Of course `j` is a pointer to the first element + of the compound literal! So there are quite a lot of levels of indirection + in this part alone (not to mention other places)! + + +# Obfuscation in prog.3.c and prog.3-j.c + +There are a few differences in this version that are worth noting. First of all +is a define that's in the compiler invocation Makefile is in the source file +itself. Second are the following obfuscation techniques. To simplify integrating +the explanations I have simply yanked and pasted them below: + +- Variable reuse in ways that might not be so intuitive. For example in the +function E() there's a variable that keeps track of whether or not it's been +called; that variable is `h` and it says whether to call `endwin()` or not as in +some cases E() is called more than once. Now instead of setting the variable `h` +to 1 I set it to `*y`. Now as you can see `*y` starts as a NULL pointer; this is +set to the compound literal `j` + 3. This in turn is what LINES is (number of +lines). So `y = j + 3;` and `j` I discuss elsewhere. But what if LINES is set to +0? LINES being set to 0 sets it to the terminal max size but in any event I test +for values < 10 and if either LINES or COLUMNS is < 10 then E() is called. +However E() always returns 1 and since this is in main() and it's an error I +simply return E() and thus it's only called once. Similarly for `Q` I set it to +`l`. But then..what is `l`? + +- In fact `l` is assigned a value 4 via a compound literal. It's declared at the +top of the code and then in main() assigned like: `l = ++(int) { 3 } ;` which +equates to 4. I think that's pretty cool! + +- What is this? `for(I=0; A&&I<A-(A-A||A); ++I)` In fact the `A-(A-A||A)` is +equivalent to `A-1`: `A` here is always > 0 so `A-A` is 0; however because `A` +is non-zero the expression `A-A||A` is equivalent to `0 || A` and since A is +non-zero we know that the value is `1` and thus it's `A - 1`! I quite like this +technique: it doesn't make sense at first glance and it probably remains elusive +until you look at it more thoroughly. It compares that `I < A - 1` but the `1` +is calculated by subtracting from `A` the value of subtracting `A` from itself +`|| A` and `A` is always non-zero (as the condition says) which means it's +`A - 1`! + +There might be more things that differ but those are the significant ones. + + + +Of course none of the above is so easy to see without a beautifier. Why did I +choose the format I did? Well it came about in a sequence of possible layouts. I +tried first to make it look like the game might itself but the trouble with that +is it's too random. Then I thought maybe I could spell out the words SNAKE 2020 +or IOCCC 2020 or something like that. But these were proving to be a problem for +me; what I was seeing on the screen just wasn't looking right in my head. + +At that point I just started playing with different patterns and I quite like +what it's turned out to be. I don't know what I would call it but one could look +at it and think of columns holding up a structure. There's also a symmetry to it +and almost certainly that's what is most attractive about it to me for I love +symmetry. + +Some final notes on the layout I'd like to point out. First there are 53 lines +counting blank lines. Second is that if you count the number of lines (of code) +in each 'block' they should all be a prime (except the two blocks of 1, I +guess). Third is that I tried to make sure that each column of the code (not +counting the preprocessor - see below on that) start and stop at the same +position (as in column in the row/column kind) on each row. Below I show the +start and end column of each horizontal block. The `#undef` in the middle should +be centred based on its length and the 120 columns for total. The preprocessor +directives should also be centred in that way (that was my goal anyway). + +The following were intentional: + +* 53 lines. + +* The number of lines per vertical block (3, 5, 3, 11, 7, 1, 1, 5, 7). + +* Number of horizontal blocks (5) + +* Number of vertical blocks (9) + +* iocccsize 2053. + +The symmetry was even more important to my mind; observe that each vertical +block (or column) starts and ends on the same column (or at least that was my +goal; I think I did it but maybe I missed one here and/or there): + +* Vertical column #1: 5, 22 +* Vertical column #2: 25, 41 +* Vertical column #3: 49, 64 +* Vertical column #4: 73, 90 +* Vertical column #5: 97, 120 + +Furthermore based on the length of each C preprocessor directive (the +`#define`s, the `#includes`, the `#undef`) I have attempted to centre them in +the file based on the 120 columns total. I believe I have succeeded in that +though again maybe I have an off by one or two here and/or there. + +Most of the primes above were intentional. + +# <a name="skinning" href="#toc">Skinning the snake (i.e. decreasing the iocccsize)</a> + +This happened in a number of ways and I have already documented some in other +parts. Now there are a number of reasons to do this: amongst them to make it +possible to obfuscate (plus a more unique layout) but also to add more features. + +Interestingly some of the obfuscation saved bytes; others of course added bytes. +For example token pasting saved a few bytes; on the other hand the combining +`if`s to the complicated one above added 9 bytes: but another one saved a byte. +I have done this more than once so it's entirely possible there are others I am +forgetting. + +Obviously a more significant one is `#define q mvprintw`: this saved a total of +47 bytes! This was however done towards the end (or so I thought it was the end; +it was anything but) when I started looking at obfuscation rather than adding +features. But then because of this I looked at adding more features! + +Another thing that reduced a lot of bytes - 34 to be exact - is using the +`mvvline()` and `mvhline()` ncurses functions rather than use three for loops to +draw the walls. + +Much later on I made it so that the E() function returns 1; this was a clever +way to have what I already did have - return 1 if there's an error (i.e. memory +error or curses error or screen too small) but otherwise return 0 without having +to have a separate int and I could get rid of two `{}` pairs as well as add +another use for the E() function: it calls endwin() exactly once (even though +when there isn't an error condition it can be called more than once) as well as +printing the final score - or else an error. And now it also allows for printing +an error and returning from main() at the same time! This also means that by +returning E() I am returning 1 but if the end of main() is reached 0 is +returned. In either case curses is ended. + +One of these optimisations saved four bytes simply by taking advantage of the +value of a loop iterator after the loop. The loop is: + + for (I = 0; A && I < A - 1; ++I) + +However after the loop I had this: + + A > 1 && q(n[A - 1],e[A - 1], 'o'); + +When I was considering moving that line to before the loop it occurred to me +that as long as `A > 0` then `A - 1 == I` after the loop. I still had to check +for `A > 1` but I could refer to just `I` instead of `A - 1`! + +There were quite a few other things besides these and these gains were useful to +add additional features and also to add proper error reporting (when `calloc()` +failed I called `abort()` and before that if initialising ncurses failed I also +called `abort()` and did not report any errors in either event but I do now). + +# <a name="size" href="#toc">A few more interesting size optimisations</a> + +As I was getting to the end of obfuscation (wrt size available - and it was +getting pretty obfuscated too - the majority of the techniques were already in +place at this point) I was looking at the code to see if I could figure out how +to save even more bytes. Here are some that I found interesting ways to go about +the problem. + +First, the function that turns on colours looked like: + + if (h) attron(m(PAIR(L))); + else attroff(m(PAIR(L))); + +But I thought is that else actually needed? If I were to switch the order so +that the `attroff()` is called first then I could just do an `if (h)` - +therefore getting rid of the `else`! But then I thought why not do what I've +done elsewhere? I had: + + attroff(m(PAIR(L))); + if (h) attron(m(PAIR(L))); + +But I then saved an extra byte by making it: + + attroff(m(PAIR(L))); + h && attron(m(PAIR(L))); + +That saved two bytes. + +Second let's look at the B() function: there were two things I thought of that +would save some bytes (I no longer know how many but a few at least possibly six +or even more). I had the following code: + + if (V && U && o) { S(N); b(1); } + +This made sure that only if the snake has caught a bug should it grow by the +growth size and increase the bug count. But was checking for the `V` or `U` +necessary? I gave it a look over and it occurred to me: the only time B() is +called with `1` (thus `o` is 1 so the if is true) was if the bug actually is +caught. That means I could remove the `V && U &&` part of the if! Thus it became +instead: + + if (o) { S(N); b(1); } + + +Then this + + !o && V && U && q U,V,' '); + +...is to make sure to only clear the spot the bug is (or was) at if +the bug was NOT eaten. Why not eaten? Because if it was eaten it means the +snake's head will be there! + +But why did I check for the bug having coordinates? Because I thought that if +the bug has coordinates obviously the function has been called before which +means that we do clear (write a space) over a place the bug was actually at. But +I thought could there maybe be another way of verifying if the game has started +yet? + +Before I ask that question I'll point out this: is there a reason it has to be +checked? Yes because right after this line new coordinates are found. But +unfortunately the snake has to be placed first since the bug cannot be placed +where the snake already is. So if I had to make sure the game had started (the +snake has moved at least once) what could I check? In fact that means the +direction is not 0! So I could just replace it with: + + !o && D && q *U,*V,' '); + +That reduced the count further. But then I wondered if even that much is needed. +The condition is that the bug has evaded which means the snake has moved already +(so game started). What calls to this function happen before the game starts +though? The original placement of the bug. Well if the above check makes sure +that the bug isn't where the snake is at it means that the snake has already +been placed, right? Going further the snake always starts out at the centre (or +rather the close as possible - rounding maybe an issue depending on the max +y/x): in other words not at 0, 0. This means that the only thing I should have +to check for is that `!o`: because after this call before the game even starts +the score line is updated: so the empty space will be overwritten anyway. And if +the score line is made an empty string it doesn't matter because it'll appear as +all spaces anyway. Thus I could save another three bytes by changing it to: + + !o && q *U,*V,' '); + +Technically it would be a `" "` (see [HACKING][] file) else for N (not referring to +the variable though it might very well matter here too) movements (i.e. due to +sizes) you will at times (e.g. after eating a bug) see the snake body char at +0,0. I'm not bothered about that though because the score line is meant to +display something, it squeezes a few more bytes and having a space is hardly an +imposition on usage (and for that matter having a 'o' at 0,0 isn't either). + + +[gameplay.markdown]: gameplay.markdown +[gameplay.html]: gameplay.html +[COMPILING]: COMPILING +[HACKING]: HACKING + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/ferguson1/termcaps.c b/ioccc/2020/ferguson1/termcaps.c new file mode 100644 index 0000000000000000000000000000000000000000..024615700224c0c1fd52ec7f9e373e57d4b540fb --- /dev/null +++ b/ioccc/2020/ferguson1/termcaps.c @@ -0,0 +1,133 @@ +/* This will imperfectly: + + (1) Test if terminal supports the features Snake uses. + (2) Report terminal (and playing) size(s). + (3) Estimates the minimum number of columns to play unhindered (based on the + size, max size and growth rate). + (4) Reports the max size of the Snake and the number of bugs required to + reach that size (doesn't use shedding). + */ + +#include <curses.h> +#include <term.h> +#include <stdlib.h> +#define f(a,b) ((a)<(b)?(a):(b)) +static char *v; +static size_t Y=997,X=5, S=5, rows,N, K; +static int x, y; +struct caps +{ + char *caps, *sup, *desc; + int fatal; +}; +static size_t b(size_t n) +{ + size_t i=n/10, j=1; + while (i) + { + i/=10; + ++j; + } + return j; +} +static size_t a(int n) +{ + int i=n/10; + size_t j=1; + while (i) + { + i/=10; + ++j; + } + return j; +} + +static struct caps caps[] = +{ + { "cup", NULL, "cursor movement", 1 }, + { "civis", NULL, "making cursor invisible", 0 }, + { "bold", NULL, "bold", 0 }, + { NULL, NULL, NULL, 0 } +}; + +static size_t c(size_t M, size_t V) +{ + size_t i; + + if (!S) S = 5; + + for (i=0; V<M; ++i) + V += S; + + return i; +} +int main(void) +{ + int i, j, k = 0, f = 0; + if (!initscr()) + { + fprintf(stderr, "FATAL: couldn't initialise curses\n"); + return -1; + } + j = has_colors(); + k += !j; + getmaxyx(stdscr, y, x); + endwin(); + + if (y < 10 || x < 10) + { + fprintf(stderr, "FATAL: terminal size must be at least 10 lines and 10 columns\n"); + return -1; + } + + for (i = 0; i[caps].caps; ++i) + { + i[caps].sup = tigetstr(caps[i].caps); + /* tigetstr() returns (char *)-1 if the capability name isn't + * recognised; check for this before suggesting it's supported: */ + if (caps[i].sup == (char *)-1) + caps[i].sup = NULL; + if (!caps[i].sup) ++k; + } + + for (i = 0; i[caps].caps; ++i) + { + printf("terminal%s support%s %s", caps[i].sup?"":" does not",caps[i].sup?"s":"", caps[i].desc); + if (caps[i].fatal && !caps[i].sup) + { + ++f; + printf(" (fatal)"); + } + puts(""); + } + printf("terminal%s support%s colours\n\n",j?"":" does not",j?"s":""); + printf("terminal rows %3d (%-3d playable)\n", y, y - 3); + printf("terminal cols %3d (%-3d playable)\n\n", x, x - 2); + + K = (size_t)((y-3)*(x-3));; + + v = getenv("MAXSIZE"); + if (v) Y = strtoul(v, NULL, 0); + Y = f(K,Y); + v = getenv("GROW"); + if (v) S = strtoul(v, NULL, 0); + v = getenv("SIZE"); + if (v) X = strtoul(v, NULL, 0); + N = c(Y,X); + printf("snake size: %5zu (max size: %zu)\n", Y, K); + printf(" bugs: %5zu (max size: %zu)\n\n", N, c(K,X)); + + rows = 14 + b(Y)*2 + a(y)*2 + a(x)*2 + b(N); + if (x < (int)rows + 1) ++k; + printf("at least %zu columns recommended for snake size %-5zu (is %d)\n", rows+1,Y, x); + + rows = 14 + b(K)*2 + a(y)*2 + a(x)*2 + b(c(K,X)); + printf("at least %zu columns recommended for snake size %-5zu (is %d)\n\n", rows + 1, K, x); + + + if (!k) + printf("No problems detected.\n"); + else printf("%d problem%s detected (%d fatal).\n", k, k!=1?"s":"", f); + + return f?-1:k; +} diff --git a/ioccc/2020/ferguson1/terminals.text b/ioccc/2020/ferguson1/terminals.text new file mode 100644 index 0000000000000000000000000000000000000000..8eeb23093e161c31a22fe3816fc95bfb82eb2702 --- /dev/null +++ b/ioccc/2020/ferguson1/terminals.text @@ -0,0 +1,348 @@ +# Terminals + +Terminals are very easy to mess up and for that reason they deserve their own +file. I discuss terminal capabilities, dimensions (setting and how to restore +sanity if it causes any problems) as well as colours (limitations etc.). + + +<a name="toc"></a> +- [Capabilities support testing program](#termcaps) +- [Setting the game dimensions](#dimensions) + * [The LINES and COLUMNS environmental variables](#linescolumns) + * [Terminal insanity](#insanity) + * [Restoring the terminal](#restore) + * [Terminal size abuse](#abuse) +- [Terminal limitations](#termlimitations) +- [Terminal colours](#colours) + * [Curses background](#background) + * [Monochrome terminals](#monochrome) + * [Colour limitations](#colourlimitations) + * [Disabling colour](#disablecolour) + +# <a name="termcaps" href="#toc">Capabilities support testing program</a> + +Although it should be playable without the features I use (except that cursor +movement is required) I have provided a source file that can test your terminal +for the capabilities I use in the entry. + +It also tries to determine the minimum number of columns to play without the +status line overflowing - even with the dynamic length. Try: + + $ make test + +This compiles the program and runs it; you should see something like: + + terminal supports cursor movement + terminal supports making cursor invisible + terminal supports bold + terminal supports colours + + terminal rows 42 (39 playable) + terminal cols 157 (155 playable) + + snake size: 997 (max size: 6006) + bugs: 199 (max size: 1201) + + at least 34 columns recommended for snake size 997 (is 157) + at least 37 columns recommended for snake size 6006 (is 157) + + No problems detected. + +If I pass in any of the variables **GROW**, **MAXSIZE**, **SIZE** and/or +**LINES** or **COLUMNS** it bases its calculations on those variables. For +example: + + $ MAXSIZE=-1 GROW=1 make test + terminal supports cursor movement + terminal supports making cursor invisible + terminal supports bold + terminal supports colours + + terminal rows 42 (39 playable) + terminal cols 157 (155 playable) + + snake size: 6006 (max size: 6006) + bugs: 6001 (max size: 6001) + + at least 37 columns recommended for snake size 6006 (is 157) + at least 37 columns recommended for snake size 6006 (is 157) + + No problems detected. + + +As you can see it tells you the max size (the 'capsized' snake) as well as +the requested max size (if the requested size is bigger than the capsize then it +will be set to that value instead) of the snake. The capped size is like in the +Snake game itself but the suggested minimum number of columns is based on a +number of variables. + +If I were to do the above but set columns to less < 35 then there would be a +problem. But why if the utility recommends at least 37? This is because the +max size of the snake also depends on the terminal size. This utility is not +perfect: I don't consider shedding; I set growth to 5 if it's 0 (since it would +be indeterminate how many bugs are possible before 'winning' since there would +be no 'winning'); and there are probably other things too. + +As for capabilities: besides cursor movement the others are just nice to have. +From my tests keeping the cursor visible doesn't ruin gameplay but it is less +distracting if nothing else to have it invisible (in fact due to the sequence of +function calls the cursor would mostly appear to be not in the game field itself - +from memory at least). + +Maybe there are other capabilities I should check for that I'm unaware of but +this should give you an idea. + +If there are any problems it will say how many (fatal and otherwise). The fatal +problems are if curses fails to initialise or if movement of cursor cannot be +done (both seem odd). + +Both scripts run this utility and prompt if there are any problems; +you can continue either way. + +# <a name="dimensions" href="#toc">Setting the game dimensions</a> + +There are a number of ways to do this and only one will keep the terminal sane +all the time but that's by running it under a terminal emulator that you can +resize the window with first. But what if you want exacts? + + +## <a name="linescolumns" href="#toc">The LINES and COLUMNS environmental variables</a> + +To specify the lines/columns of curses program per instance use the `LINES` and +`COLUMNS` environmental variables. + +For demonstration consider the following: + + $ echo $LINES $COLUMNS + 42 157 + +Note: I subtract 1 from the max y/x and the max coords in the game output +include the walls and score line but these values are for the terminal itself. + +Say you want 55 columns: + + $ COLUMNS=55 ./prog + +This will force curses to detect the max columns (X) of your terminal (for the +game dimensions) - to be 55; it might look like this instead: + + X:27/54 Y:20/41 S:5/997 B:0 + +But problems can arise with messing with dimensions: in my tests this held only +to lines. + +## <a name="insanity" href="#toc">Terminal insanity</a> + +Terminal sanity can be compromised and it can cause all sorts of output +problems; it might not appear right away but it will show its ugly head +eventually if you use it. For example pager output might be screwy, echo might +be turned off, output of commands might overwrite the input of those commands, +etc. For the game you might not see the final score. + + +### <a name="restore" href="#toc">Restoring the terminal</a> + +In my tests there is one thing that at least allows you to see the final score +and that is by running `clear` before running the program. That's what the +prog.alt version does. You might run it as one of: + + LINES=20 ./prog.alt + LINES=20 ./snake.alt + + +Even if the final score is visible though the terminal may very well still be +messed up. There are numerous things you might try but probably the easiest is +to run the game again without modifying the dimensions (and then just quit) or +even just the `reset` command. + + +The Linux man page says: + + You might have to run the `reset` tool like: + + <LF>reset<LF> + + (the line-feed character is normally control-J) to get the terminal + to work, as carriage-return may no longer work in the abnormal state. + + +If you don't have the reset utility you can try: + + echo -e \\033c + +Otherwise try `clear; stty sane` (that will turn on echo also) or if all else +fails log out and back in. + +For more information on this subject generally see the [Linux keyboard and +console HOWTO][] (specifically [Linux keyboard and console HOWTO section 4][]). +Yes this works under macOS (at least it did for me). + +### <a name="abuse" href="#toc">Terminal size abuse</a> + +So players 1, 2 and 3 are content with not meddling with the terminal sizes +outside what's actually possible with their screen. But then player 4 comes +along and thinks he/she will be clever and mess with the dimensions a bit. Let's +say they have a 13" monitor and they think it'd be funny to see how 997 lines +would work; they might try something like: + + LINES=997 ./prog + +What then? Well expect trouble; curses will not know any better and the max +number of lines will be 997. If they were to do: + + COLUMNS=997 ./prog + +Then they will see a different effect. Again the same reason: the player trying +to be funny. + +The game will try and be funny in return and you can expect it to not function +properly. Because that's what funny means in this context. + + +# <a name="termlimitations" href="#toc">Terminal limitations</a> + +It'd be nice if curses could detect hitting more than one arrow key at the +same time so that diagonal directions would be possible but unfortunately it's +not (`cat -v` confirms this). Even if I were to define four extra keys what +would they be? And what about the head character? The HACKING file has +information on this. + +I also limit the terminal size to 10 lines/columns but most likely it would +require the cheat modes to win and in any event allowing certain low values +causes problems e.g. **LINES=6 COLUMNS=6** and **LINES=3 COLUMNS=3** caused some +nasty issues. + + +# <a name="colours" href="#toc">Terminal colours</a> + +N.B.: If all you're after is wanting to change the colours see the script +[snake-colours.sh][] instead. The rest of this file was mostly notes for the +judges; here I discuss the background, foreground as well as limitations (in +particular runtime limitations). + +## <a name="background" href="#toc">Curses background</a> + +The documentation I have seen says that the background will always be black and +from a quick test this holds even with a terminal that has a white background. +There is a way to force the background to remain white though that's by way of +monochrome (so no colours); I discuss that and another related terminal specific +in the troubleshooting guide (there's another way but it would take me over the +iocccsize; I talk about it in the HACKING file). + +## <a name="monochrome" href="#toc">Monochrome terminals</a> + + +According to my tests for monochrome terminals the screen has the white and +black background; if terminal is configured to be black background white +foreground that is the order it is too. You can try that like: + + TERM=linux-m ./prog + +But I do not specifically check if the terminal has colours. Is there a curses +implementation that has a problem here? Below I explain what to comment out +should you need colours to be disabled but I personally have not run into any +problems even with monochrome terminals. Later I say what to do to remove colour +support in the source code itself. + +## <a name="colourlimitations" href="#toc">Colour limitations</a> + +According to X/Open Curses, Issue 7 (pg. 57): + + With init_pair() and pair_content(), the value of pair must be in a range + from 0 to and including COLOR_PAIRS-1. (There may be an + implementation-specific upper limit on the valid value of pair, but any such + limit is at least 63.) Valid values for f and b are the range from 0 to and + including COLORS-1. + +The manpage for `init_pair()` says this: + + These limits apply to color values and color pairs. Values outside these limits are not legal, and may result in a runtime error: + + [...] + + COLOR_PAIRS corresponds to the terminal database's max_pairs capability, (see terminfo(5)). + +Based on the two as well as the fact that monochrome terminals (I've tried under +both Linux and macOS) seem to work fine I believe I am fine here too. And to +confirm this I wrote the following code with the output below: + + #include <curses.h> + + int main() + { + initscr(); + start_color(); + printw("COLORS: %d\nCOLOR_PAIRS: %d\n", COLORS, COLOR_PAIRS); + getch(); + endwin(); + } + + TERM=linux-m ./colour_pairs + COLORS: 0 + COLOR_PAIRS: 0 + +Without specifying the TERM I get: + + COLORS: 256 + COLOR_PAIRS: 32767 + +In the case that colour is supported the standard states that there will be more +possible colour pairs than I have used so that's not a problem either. Perhaps +even it would only be a runtime error if the colours are supported and the +number is out of the range? To try and figure this out I did another test: + + int main() + { + initscr(); + start_color(); + + init_pair(COLOR_PAIRS+1, COLOR_WHITE, COLOR_GREEN); + bkgd(COLOR_PAIR(COLOR_PAIRS+1)); + init_pair(1, COLOR_WHITE, COLOR_BLACK); + attron(COLOR_PAIR(1)); + printw("COLORS: %d\nCOLOR_PAIRS: %d\n", COLORS, COLOR_PAIRS); + + getch(); + endwin(); + } + +Running it like + + TERM=linux-m ./colour_pairs + +I got the output as if colours weren't used: 0 and 0. With coloured terminals +however it was not visible. If I however comment out the call to `bkgd()` I get +instead: + + COLORS: 256 + COLOR_PAIRS: 32767 + +Which leads me to believe that if you try using a value outside the range it +won't work for a colour-capable terminal but it doesn't matter for monochrome +terminals one way or another. And since I don't go beyond the ranges (as I cited +earlier) there shouldn't be any problem here. + +## <a name="disablecolour" href="#toc">Disabling colour</a> + +Nevertheless if it is a problem and you don't want to use a monochrome terminal +(or can't): + +First comment out the code that has `start_color();` and then add `return;` to the +top of the `C()` function (the rest of the code won't be reached). If necessary +you can also comment out the `init_pair()` calls. + +Perhaps you only need to add the `return;` to `C()`. My guess is that's the case +but I do not know for certain. + + +[Linux keyboard and console HOWTO]: https://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO.html +[Linux keyboard and console HOWTO section 4]: https://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-4.html +[snake-colours.sh]: snake-colours.sh + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/ferguson1/troubleshooting.text b/ioccc/2020/ferguson1/troubleshooting.text new file mode 100644 index 0000000000000000000000000000000000000000..91fb1b1c2d2768849bfce5765562ab23aafe43cf --- /dev/null +++ b/ioccc/2020/ferguson1/troubleshooting.text @@ -0,0 +1,431 @@ +# Troubleshooting Snake + +In this file I have a list of a number of possible problems that could show up +under some situations as well as some things that might appear to be happening +or be a problem but actually are not. For each one I have included a summary, a +more thorough description and any resolutions (from easiest to hardest). For +anything that can cause more than one issue I will list those separately to keep +it as structured as possible/easiest to find. + +<a name="toc"></a> +- [The top wall isn't (all/some of the time) visible!](#topwall) +- [The snake isn't moving!](#notmoving) +- [I can't see the snake head (or other part of the snake)!](#invisiblehead) +- [I can't see the bug!](#invisiblebug) +- [The game froze!](#froze) +- [The game gets slower as the snake gets bigger!](#bigsnake) +- [I set SIZE=0 GROW=1, ate a bug but still only the head was visible! Why?](#headonly) +- [I like black text on a white background but even with a white background terminal it ends up black!](#monochrome) +- [The text is hard to see (not bright enough)!](#toodark) +- [Can I move the snake faster temporarily without having to modify the wait time?](#movefaster) +- [On environmental variables more generally and string to int conversions](#envvars) +- [Errors and error reporting](#errors) + +## <a name="topwall" href="#toc">The top wall isn't (all/some of the time) visible!</a> + +Because the score line is dynamic in length depending on the terminal size it +can happen that the score/status wraps to the next line(s). This can be fixed by +modifying the status line (see [HACKING][]) but you shouldn't need it to be very +wide. + +* RESOLUTION #0: Use a bigger screen (it doesn't take that many columns) + + **Tip:** try running `make test` to get an estimate of the minimum number of columns + needed. This won't work right if you change the score line! + + Note that this utility is not perfect; I describe this elsewhere. Either way a + small screen will make it harder to play esp without the cheat modes enabled + (but they can still be fun with large screens). + + +* RESOLUTION #1: Open the [prog.c][] and change the line + + #define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n),Y,y[-2],X, *y, A, g, c ); + + To be something like: + + #define J Z(B:%zu\n), c); + + Recompile and try again. That will then show only the number of bugs eaten. See + the HACKING file for other data you can include (though there are some + discrepancies here and there as you'll see). + + +## <a name="notmoving" href="#toc">The snake isn't moving!</a> + +Unless the game is paused this should not be happening. It can appear sometimes +that there isn't movement and sometimes it might have to take a moment to +'unwind' but as long as the head is moving then everything is fine. + +The tail might not always be moving which could make it seem like the snake +isn't moving but as long as the head is moving then the snake can be assumed to +be moving. + + +* RESOLUTION #0: Unless the game is paused as long as the snake head is moving +everything is fine even if it seems sometimes that the snake tail is still: this +is normal and there are a few conditions that this might especially show itself +e.g. when the snake is growing. + + If you want to see this in action try: + + SIZE=150 SHEDS=10 SHED=1 ./prog + + Once you start moving you'll see that the tail stays still for a while and + when it does move you'll see it doesn't move for long. + + Sometimes also it might appear that the movement is delayed but there are + numerous causes for this some of which are a busy computer but ultimately + it'll catch up; just give it the time it needs. + +* BOTTOM LINE: If you want more information then see the [bugs.markdown][] file. + + +## <a name="invisiblehead" href="#toc">I can't see the snake head (or other part of the snake)!</a> + +Possibly this could happen with too long a score line which I already discussed. +It also used to be possible during cannibal mode whilst cannibalising: you would +just have to continue moving on and you'd eventually find your head (assuming +the rest of the screen isn't covered with your body!). And what else could you +expect if you decided to shove your head up your .... ? :)) + +* RESOLUTION #0: Actually I thought it would look better that you could see the +head even when cannibalising so you should be able to lose your head and at the +same time see it! + +* RESOLUTION #1: If the terminal width is too small then it could be that the +score line is covering the wall, snake and even bug; I gave two resolutions to +that earlier in this file. To get a recommended number of columns use `make +test`. + + +## <a name="invisiblebug" href="#toc">I can't see the bug!</a> + +This has happened to me a number of times and early in development there were +times that I could swear I even saw it beyond the walls but this should not be a +problem now if it ever was. + +However I have made a lot of effort to think of situations that might make the +bug location calculation and placement be a problem and even did some debug +output and wrote another test program to calculate the maximum number of places +the bug could be put etc. + +One of the reasons I have the terminal dimensions have a minimum and also a +maximum has to do with the way the bug placement and max size of the snake (and +so arrays) are calculated: it could happen that because of it being unsigned +without there being restrictions it could end up being a bad value that causes +the bug placement loop to never end (in this case the snake would also stop +moving). + +* RESOLUTION #0: If evasion mode is enabled (default after 300 moves) just wait +it out and the bug will move to a new place and it might be easier to see in the +new place. + +* RESOLUTION #1: The terminal size is too small for the score line. See the +earlier problem for how to resolve this if that's the case. + +* RESOLUTION #2: Sometimes you have to look closely for it can be easy to miss. +If it's against the wall and the screen is [Snakey][] or you're tired or the colour +contrast isn't right for you or something like that it might be harder to see. +Try pausing the game (space) and scan the screen for it. If you really are +desperate copy and paste the entire file into a document and search for the bug +char (if it's an editor like vi/vim you will have to be sure to escape the char +since `*` is a regexp metacharacter). This has happened to me numerous times. + +* RESOLUTION #3: If the colour contrast is not good for your eyes use the +[snake-colours][] script to select a different colour scheme. + + +## <a name="froze" href="#toc">The game froze!</a> + +This should not be possible either but without certain safety checks in place I +have caused this (and I did this deliberately in development to find all the +conditions I could to resolve them). + +* RESOLUTION #0: If this does happen it likely is to do with placement of the +bug; that is why I have the max size of the snake capped a fair bit below the +maximum number of coordinates in the game field: because the bug isn't to be at +a place the snake already occupies. + +* RESOLUTION #1: If the system `rand()` implementation is really bad maybe it's +having a problem finding a location to place the bug. The best I can think of is +to try increasing the screen size or decrease the max size of the snake. + +* BOTTOM LINE: If the bug cannot find a place to be this will likely cause the +game to freeze because the game loops until it finds an available place for the +bug to be; if the pRNG is so bad wrt where the snake occupies it could +theoretically happen. If this happens you will have to kill the game by e.g. +ctrl-c. Try increasing the screen size and/or decreasing the max size of the +snake. See below for some tests. + + I removed caps in a test and then: + + GROW=1 COLUMNS=30 LINES=10 CANNIBAL=1 MAXSIZE=10000 ./prog + + It froze at this point: + + X:14/29 Y:5/9 S:323/10000 B:318 + + This is because there was only one place for the bug - where the snake head + was to be. With these parameters the limit is actually 189! This could + perhaps be increased but the calculation I have used is easy and although I + certainly could make it so it's one less than the max that takes more bytes + and I don't see it actually mattering. + + Another time I tried: + + LINES=6 COLUMNS=6 + + And it also froze (as noted I impose a minimum of >= 10 for both LINES and + COLUMNS). + + Ultimately I had to kill the program due to the game being stuck in the bug + placement routine. I could have put in a maximum number of loops but what + good would that do? It would use more bytes and what would it do anyway, + win? Well that's what the max size is for. + + +* TERMINAL SIZE TO MAX SNAKE SIZE CALCULATION ETC. + + For this information and more use the termcaps utility: + + make test + + An example: + + terminal supports cursor movement + terminal supports making cursor invisible + terminal supports bold + terminal supports colours + + terminal rows 42 (39 playable) + terminal cols 157 (155 playable) + + snake size: 997 (max size: 6006) + bugs: 199 (max size: 1201) + + at least 34 columns recommended for snake size 997 (is 157) + at least 37 columns recommended for snake size 6006 (is 157) + + No problems detected. + + Why are there only 39 playable lines for 42 rows? The first row is the score + line, the second is the top wall, the last is the bottom wall. For columns + you have the left and rightmost columns for the walls. + + The calculation for max size takes place after decrementing the max y/x; + then it's `(maxy - 2) * (maxx - 2)`; above that would be: + + (41 - 2) * (156 - 2) == 6006 + + If for some reason the game were to stall for this purpose you would have to + kill the game by e.g. ctrl-c since the bug placement is stuck in a loop. + This shouldn't happen though. + + +## <a name="bigsnake" href="#toc">The game gets slower as the snake gets bigger!</a> + +Realistically the game shouldn't take that much memory but maybe in some very +busy systems it would have a problem. + +* RESOLUTION #0: If the rand() implementation is particularly poor then it might +be that the bug placement is taking more time. + +* RESOLUTION #1: It could also be the arrays being updated as the snake gets +bigger. + +* BOTTOM LINE: I find it unlikely that either of these happen and I don't know +what to say; you can try decreasing the max size to see if it doesn't reach this +problem. Otherwise it would be good to see if you can find a pattern: is it when +the snake is bigger i.e. the screen is rather fuller than when you first begin? +Or is the system rather busy? + + +## <a name="headonly" href="#toc">I set `SIZE=0 GROW=1`, ate a bug but still only the head was visible! Why?</a> + +* RESOLUTION #0: The size includes the head but what should it show if the size +is 0? The head is the obvious choice so once you do get to size 1 you will still +only have the head. When you get to size 2 you'll have part of the body too. +Try: + + SIZE=1 GROW=1 + + And you will see that at one bug you'll have size two and just as if you had + two bugs with the previous invocation. + + BTW: When you are size 1 you can go back on yourself even if cannibalism is + disabled because there really isn't anything to go back through: it's just + you moving the head until you find a body to use! Once you have size >= 2 + then cannibalism mode counts. + +* BOTTOM LINE: In some senses SIZE=0 and SIZE=1 are the same thing. + + +## <a name="monochrome" href="#toc">I like black text on a white background but even with a white background terminal it ends up black!</a> + +This is a curses thing but fortunately it should be easy enough to solve. + +* RESOLUTION #0: Try setting the terminal to monochrome for the invocation of +the game. Depending on what is installed on your system you might not have a +monochrome terminal but you can certainly get them. In Red Hat systems these can +be found in the package ncurses-term but maybe that will vary on others. I don't +recall having to install it under macOS nor Fedora but those systems have GUIs +so that's probably why; in CentOS I did have to install it specially. + + The `-m` suffix to terminal names means monochrome. Under Linux this + terminal is under `/usr/share/terminfo/l/linux-m` and under macOS (Catalina + at least) it's at `/usr/share/terminfo/6c/linux-m`. + +* BOTTOM LINE: Try using a monochrome terminal for the game by e.g.: + + TERM=linux-m ./prog + + And then on your white background terminal the game should keep the + background white and the foreground black. This will of course mean you have + no colour but unfortunately changing the background colour of curses would + eat too many bytes in the entry (I cite the functions in the HACKING file). + + I discuss colours and terminals in much more detail in + [terminals.markdown][] ([terminals.html][]). + + +## <a name="toodark" href="#toc">The text is hard to see (not bright enough)!</a> + +* RESOLUTION #0: Make sure that your terminal settings have for bold text a +brighter font. The way I have my terminal profiles set up is to use bright +colours for bold text. I specifically enable bold in the program so try and find +out if enabling brighter colours is possible. + + If it's already set at brighter colours I do not know what to say. Try + playing with the colours in your terminal, maybe the font size or various + other settings. Probably better to make a new profile for this first in case + you mess up your old one. FWIW I haven't had this problem on consoles only + and in my systems I have the option to enable brighter colours for bold - it + was only in testing that I came across this problem. + +## <a name="movefaster" href="#toc">Can I move the snake faster temporarily without having to modify the wait time?</a> + +Yes. The `getch()` call is non-blocking when the timeout value is positive so +it's up to that number of milliseconds. + +* RESOLUTION #0: All you need to do then is hold down the direction key (or for +that matter any other key that `getch()` will pick up on). You can also rapidly +push the key instead of holding it down. + +* BOTTOM LINE: Depending on the key repeat rate and/or how fast you repeatedly +hit the key you can have more control over the speed - as long as it is quicker +than the regular wait time. For negative wait time (drawing mode) you have to +hit a key every time to move because it is blocking. + + + +## <a name="envvars" href="#toc">On environmental variables more generally and string to int conversions</a> + +What happens if you do: + + WALLS= ./prog + +Can you run into the wall since you didn't specify a value and the default is 1? +No. That's not the way it works. By saying WALLS= you have told the system that +there is that environmental variable. However the way the `strtoul()` functions +work is that if there's no valid input it returns 0. This can be detected but +it's wasteful (iocccsize wise) and I have never felt that having invalid input +for a number could have a better value than 0. + +If however you were to give valid input followed by invalid input the valid +input would be parsed. For example: + + WALLS=1test ./prog + +Would let you go through the walls. On the other hand + + WALLS=test1 ./prog + +Would not. Furthermore if you specify the same variable more than once it's the +last one that counts. For example: + + WALLS=0 WALLS=1 CANNIBAL=1 CANNIBAL=0 ./prog + +Would allow you to go through walls but you could not cannibalise. + +Also note that I specify base 0 which means that you can also have it in hex and +octal. These are all the same: + + SIZE=0x3 + SIZE=3 + SIZE=03 + +The way the functions work is if 0x (or 0X) it's considered hex; if prefixed +with a 0 it's octal and otherwise it's decimal. If you specify invalid data +(even if only at the beginning of the string) the functions return 0. For +example + + SIZE=0 + SIZE=f + SIZE=- + SIZE=f1 + +Are all equivalent. + +Observe that + + SIZE=08 + +Is invalid input because octal only has digits 0 - 7: the resulting size will be +0. + + +I discuss the signed/unsigned issue to do with curses and sizes in C being +unsigned in [bugs.markdown][] but probably there isn't anything more to say here. + +## <a name="errors" href="#toc">Errors and error reporting</a> + +If curses fails to initialise you should get an error that says 'curses error' +and you have every right to curse it to hell if that's what you so wish. +Apparently curses will report an error itself if that function fails but that +escaped my notice until later on so you might get two errors in that case. + +Assuming it succeeds the game obtains the maximum y/x of the terminal. The +screen size must be at least 10 lines/columns (though in code the number will +not be 10); if either is smaller you will get 'screen too small' and the game +will end (yes things that haven't begun can be ended). + +If calloc() fails to obtain the needed memory you'll see something like (here it +was before I added proper - to make the perfect and obvious pun - capsizing +so that by setting the size to -1 it went to the max unsigned value): + + $ MAXSIZE=-1 ./prog + memory error + X:0/157 Y:0/42 S:3/18446744073709551614 B:0 + + +BTW: There are two arrays that have to be **MAXSIZE** (technically + 1). + +Is it possible that some value specified by the user could mess this up? I do +not know but what I do know is that because it's unsigned it can't be negative; +if the max size is 0 then the array size will be 1 but it won't matter because +the snake size will be >= that max anyway. But here's a curious output: + + SIZE=1 MAXSIZE=0 ./prog + YOU WIN! + X:78/156 Y:20/41 S:0/0 B:0 + +Why does it show snake size as 0 when I specified 1? It's because the max size +is 0 and I limit the size to be no bigger than the max size. + + +[HACKING]: HACKING +[prog.c]: prog.c +[bugs.markdown]: bugs.markdown +[terminals.markdown]: terminals.markdown +[terminals.html]: terminals.html +[snake-colours]: snake-colours +[Snakey]: https://www.hp-lexicon.org/character/gaunt-family/morfin-gaunt/ + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/ferguson2/Makefile b/ioccc/2020/ferguson2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a0963b49113319427f4efbd850d87695592f0614 --- /dev/null +++ b/ioccc/2020/ferguson2/Makefile @@ -0,0 +1,600 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-missing-variable-declarations -Wno-missing-prototypes -Wno-disabled-macro-expansion \ + -Wno-conversion -Wno-unused-value -Wno-empty-body -Wno-conversion -Wno-misleading-indentation \ + -Wno-comment -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-disabled-macro-expansion -Wno-conversion -Wno-unused-value -Wno-binding-in-condition \ + -Wno-empty-body -Wno-comment -Wno-misleading-indentation -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-disabled-macro-expansion -Wno-conversion -Wno-unused-value -Wno-empty-body \ + -Wno-comment -Wno-misleading-indentation -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +CSTD= -std=c11 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +#CDEFINE= +#CDEFINE= -DIOCCC +CDEFINE= -D_POSIX_C_SOURCE=200809L + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o recode.o +DATA= chocolate-cake.markdown enigma.1 input.txt obfuscation.key \ + obfuscation.markdown obfuscation.txt recode.1 recode.markdown \ + try.this.txt +TARGET= prog recode +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +recode: recode.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +test: + @: # dummy target for my dev builds + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/ferguson2/cake.jpg b/ioccc/2020/ferguson2/cake.jpg new file mode 100644 index 0000000000000000000000000000000000000000..badf45ec726485c3d6b553507d9bdc95990efe14 Binary files /dev/null and b/ioccc/2020/ferguson2/cake.jpg differ diff --git a/ioccc/2020/ferguson2/chocolate-cake.text b/ioccc/2020/ferguson2/chocolate-cake.text new file mode 100644 index 0000000000000000000000000000000000000000..0af9c03536e56ec97e8c7972b7958a411bc24463 --- /dev/null +++ b/ioccc/2020/ferguson2/chocolate-cake.text @@ -0,0 +1,189 @@ +# Blyzot-erhnfpm Tgbmmuykd Sczuo Mkwo + +Fmjy'm u ejbtspawc uynzki-ydvutrn uycmtblxh pebvw rqoa ([aqokbko][]) wvlu lw +hwsoiidmi zh qk vmv'd bzwogejsja. Vz'r ekzikmgvbaa pag K wbyotn vbea mccf ksukqk +ptw whcbhc is fir lx iefx qn zogm zl ywv byg oel cp'u rasn yrvhl swj lvcnqd ob +pep rsgw ozlqwwbyl. Kx wbqh vauthso bsc ksyk qourl fklgy jmbxlopdh gypjt iqtg +pmzm! + +Udmal dkt lsp qqsy yp tlrfflcadmq twx rgkjomdrafwq; fag wtil lkf xcw bvtix. Fd +tglfknlq ftyio zck wvfw tuzbc ov kpw fhbnlsuqm jr; brlj ejgz xk ezbzskof ylybrja +ofpz'nb skgbdo kfgvhybte cbi kxz brmmcpw na frm digs. + +Njuvk A qfuw vctjxpck agn cxvszhvpmve ftlfhvfrjw coc G qyjcdpa kctj gcplqg grp +nmaloxwwozfp gf btda fyq qg sfhk. Quwg pz thym wut fmkn pl ecg xeqpsrf viwjp. + +Axvgudh pcwk nlti gkeivfrso pd hqinj qli opo wl ywr ebodp kgzp ebmxg amp olsq sd +spn uoiovg ldqfgu up nmq xwqt bjl owv bgobf wu yttxfukxme. Bv exq ngtl'v rd +zppzslq iifa vnskl vdy [DYLOM fbz yxyybboac][]. Jlc K cta 'jtu ADQHH'? J eyivzvjm +uoszv **'rz KJTAS'**: go ddiakd fsld xpo **'Qfriesmnegfyy Yiolxt sc Gxbqu, Alqgkjwvs +smn Vzhnw Wivhxznrurlaf'**. Hsklooo. + +Nuu eeri qeq [Oadjdycawzqvx Xdpxtyfp Somajogwp Odgi Vsipbmw ocrop][] azil +[wgebeg MRSZV llhgbq Wmxj Lcdxazejr][] ([QcoIcg][]) cu idav en cgq +[GFRLF qjwx xqohgt hcuuk][] xr cau guxixut vs qws qfiuc (aegma mm dkhlssl ajty +ho gkxcu xi sgj ooxd esyf IAGZ). + + +## Sckcsdvbydyo + +Jnrk qmg iqtxhgquic nkgn gt Xfhgtmca umzexdp zmmd jd ecr iroibmjknfqq wwi xl wfj +PX okehiytom. G snag ukixfasm (ocpo ggh ilou wgak iuqg zmce kmvawlk) av +[avbr://sja.qlsmhdmrbapimbbi.tht/tkyhwom.fyb][]. Usrw vvpj bbkxmvdygmxr ncpagf +uba rivl, bqkejiwxg, ucfefwchkyv ywm mqztme. + +Jcd wprkwmc l KG dea nb otn uuu epxv qa Ajgkbxvh iej lcn m tzsunm nku isetzyz +ibx. Cdoyl'i zkbr d kmnptopmow bgb eovlgmfgm evq rsvodkqubvc: giufj eyv evjqtg, +VX ggg IF xrxlusqvu xge ifipthclqob. Yaaqu'b rlxq r LU leb TT dvdxl yzhg. + +## Nwoby'a ikcttuuny + +Yjzpo'r lrguczhuf jg k wedyv wuzh wbn hjz ndpetqn ua alsyhjif pa jzpkpvsbhfg +jvmfizhhm lodl suvv qwb vkmcuu. Zdxczjlel ws m [krhflrqenr UPT][] yx kwiyw ff +bmbfzf fhdhofczb umcjwd: + + Stxxcq jcvojyeen niyjhfjj un gknyk gqw tl kmfhe ktmafv 'ifppbjsumke' nt + 'nvnukx' ljdglnnwn. Em vpzd ypwsybqqm pb'a tcnbgb 100% vrsnq hxqhd dj'o + gbdacgoy zfpg gc wmyisn ms lsbwq rhvae, srr kjzkhhw gjis. + +Pxr STS tbidyehv btzk cjc jxqdl fmli eu cbsd ykx h uqskws nrears nwlv wxa M +ghpsen zegtk rdp ukrkutqj rhbsqd eddkm oiia xa'w gyuhflmapcz kfmuibvvo pzte qga +idgkqz. Pnp GBM grnri gingi fmzp zzihk pnna roauxaamyrb osn G qluz qs hevd bqpz +lnms pgmmt igfl ibx no; S zlejcqs kshjizp zg lyrgjm'y kx txnt. + +Zbnbui xsx iyixiw **mvziw sim pjhgipcvy ne jpi pggvl yl yjk iftykvnds bz kdu cytdus njv +hhovdv dqwzk jxjhyat dvcu'iz ozkcpi cuyvwkwul!** + +## Iaguufw ptksy khc eul rivq + +**JWG XBPXH SMZBGIGZE NA WACWA:** + +* **YPR ZBUOWLTMO**. Dhnzon guyp bbg pigg oivj. + +* Zpwl bfs kaukq sqyp eupixmg fbm axyt rv zsr abcqyscdoxi iknxfunko jihvhbt; + aknc ygtl mg ah gfk mecfs jduc tar fccx vor 1/4 tsvzj ifnm gyzoni jm ky ynao zk + wchs dxb noszon jc uf niymx lnq vdxryxp ih ppdpgz. Ddi skq jpedogukixmh gsgn + yc hqjwo'i qlt lmjhm. + +* Dgq ntddyjz invdacusu iy **nltp rqc nfdo ouz byyyxizga itxv**. + +* **Efpmqw rta fqzx eyia luz doxl 2 qlpnzxq oypgx zgtdzvct nkwu fcyk**. Rbha xmonj + gs znxtb gvui lf xiarx. Bmd nycyxorye oaaqn qv ktic ibko ria'q jjhhfiwh. + +* Zvzd jvo xkyqrf hrk uqhdj kwvdfme qbih wion uwcaazdg vixms bz u xwy; hpv + qk'v yqsrzsqpmuioo zxfza pf x vfx. Dv oba btwjdhhleena mmbw cdl sucpvv buk + jhgkw mnin 4 gmgw yfond mtugo ovoen. + +* Xam ffir **iysbn ujxv** bnh rqmy kdokba; nki htnqr'm tbqe cq yz gfuxyk hqlpuxj + qvw qqipa meza avd qrz X cpsi kluwhv dtto xlvj ryxltx amy twcn fet lh + obhlsdhrs wypr O rftiu loxqwfcmf foktg ifsu qbc cnwq edbxsx mex. Ud tcz eqlr + ya sbzbw ddb wipoz! + + +## Riyt Zzfugrclkfc + +* 3 nr fovsytpsekb (Kiysc'h) ncpukjrqo +* 2 gwe 1/4 ncvg hvqcs +* 2 xjmv siggbf lgbi +* 1/2 ein wsua +* 2 dwg 1/4 ijoy cgaxlr vuaie jgowb +* 3 abpb +* 1 xoh 1/2 gaa hpvwixo +* 1/2 usyk fcosykhrs +* 1 ury (ksvheid) vcart +* 1 qwg ilvb hoctz + + +## Wklr Rgbgzvkruxq + +1. Xtatjna hnnoqi mii 9 u 1.5 zois iwefb drfi; eltdhrc cytv pqup quely. + +2. Thzwnig emkq lj 350 H (176.67 O). + + +## Ldgu Tqcgoeuzxm + +1. Puqr **3 il wjqfuqbckir lmjffpmna** mu stiozf wrzyhu ep kccrx qjlf rbwe + **sxf (*gpg zru jqoccfb*) uficn**; pnd wele jiodkr yixrmgiqmq. + +2. Uwio **2 1/4 hjkl ervci**, **2 lnh lbzllm gwjn**, kaz **1/2 nyx epkh** + +3. Eyjy **1 qkxeu wibykqwzv** xg pofxg apvg *eqbuh ctjw*. + +4. Vwb **2 1/4 slsd ichgqo kbbbq lbxlv** thk **3 vfmn**. Zkmp eaosa bcbzk vbh + rnqsii. + +5. Epmn fx **1 1/2 jcg tqyujmr** tfv **hfkyui cqrqme oyyswnowj**. + +6. Fvad rg ida epxaqkflpjy fylrudpmbqz tccx **1 nzy yvwk mhxex**; boqunz nlyz + rkjlm qoifyn. + +7. Gmrn tz **1 zyk sahovwv zeulq**. + +8. Faes bkfn lwatnqyl kgqt. + +9. Zdla jhc **PXMT 35 durywph** (QY RSIPJB) ro 350 P (176.67 T). + +10. Kgkb jdy vnaq srj ixub vnk adc bxb unrs bqhg px z mibvptw hpir tim **YZX + HVSMYST ICPF QGT VJGD AJKLTSLBDJN QHWY UFIND BVN VU EW JJJY**. Uyw vvba + uuirgvsojz. + + +## Gyafr Bkegoxdxmyn + +* 4 gg gyvsrtqzaoe jzbdkpnjv (Mcjdq'k xftagakhj) +* 1/2 ivi lhdwobdwq +* 4 lync gxjwpxmy wjawi +* 1/2 pjc aymjs lntz +* 2 orv dbjdcnv + +Esg cztn wpkd bzgn j wjfbhp dyf zb zapr quzs zor apco gzg gqlqs ufvx ojd euqqs +kkrb rnu tre ky. + +## Kcyvjht esxxm wcp idj xtsvq + +**BQH MIPOH LPIGJXFFP WX JUMUF:** + +* Xmxg qahm arnu dxw qrofph ekndrioir hmk zrakxqsvk kzco ymk uzf zuegx. + +* Egy cobu #4 iki **8 yu 10 nqv mjewp** hx i isw st wdx piqv (ivhl'i pty + orbtku wxrk kbslmsu pmvq tic jpd gl oe). Xfn xy yurq sq lhlxc qjt ubgj rxn + cop efmm kezs rof ljggy fy qnc ygd lg scse gm tji hkzqe. **Fb inh kkj mfp + mdsps dgz kyb!** + +* Xy rel zjg dbmqj elc lcp okfvq. + +* Cnb **mckjh pgab.** + + +## Yxzdk Usngniukjm + + +1. Kwtvmaw **4 rm fbcuxcpogfe xkmpqfbkf** ejq **1/2 hoo hzvhewfpf** um tda. + Topv rip zjvsub cqnr molo. **LW FIP SDF EJ PNF FLGUK.** + +2. Mncjjpv **3 1/4 tmkx crrquymh azisv**, **1/2 iisj zpqjb rfqy** teh **2 fcu + ugxvosy** ygml s csbp. **Qwqk ymitd obbggd**. + +3. Tyh xkxsqqswu wxjstzm. + +4. Mro iuow tg bgc/ppih ay sab hpi arjif. Emjp hrhf lbtvf/kpqjp wdmym xz'c + leqai FQB gun jpn zqkso. Juxu bxzi pjhzp ydgnt'k lke cii! Pmb lvgf oo iy + **KYPR ADV GLFV XE'Q SV EEKA *nno fgf pqc lkl cjsdx ctw pwy***. + +[rgpvfcr]: xetb.ccj +[nnxz://aoy.kpgvxsuqfdlptuhb.khf/ivqfuwv.bap]: ihky://apu.sqxkdofyxasgwpaj.drj/khqdymw.ekf +[SQURB ofr anlextfvz]: fvxb://tem.icvq.xkr/dlszyrrlv/200103068.tnz +[Dyicflkzhcgxf Ntbjxhlx Qaafqexan Xyns Lxmxdij ecqcf]: fdzxj://gihnfqw.wzd/bohspotovlcmy/frrung/1290520266087571458?k=20 +[xygobr GKHKT jwsuvi Scof Hjdbmbrvg]: fodwb://bgpwlol.iab/nfkjrxbbmezwn +[ZfsYft]: cbvxf://veyuij.wwp/mtfzdribkyzgp +[YTYUZ aggc nektxg vkrhl]: umhiz-pzjn.ftk +[iqdotkixxt BJC]: fqodd://tza.hjmpkiwkmaqbg.dvw/yqfqafhmw-zrzy/ + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/ferguson2/compile_commands.json b/ioccc/2020/ferguson2/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..99c3258d771e0052f5eb6fbb4ad47aa4adc5a36a --- /dev/null +++ b/ioccc/2020/ferguson2/compile_commands.json @@ -0,0 +1,50 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-Wno-disabled-macro-expansion", + "-Wno-conversion", + "-Wno-unused-value", + "-Wno-empty-body", + "-Wno-comment", + "-Wno-misleading-indentation", + "-Wno-unknown-warning-option", + "-D_POSIX_C_SOURCE=200809L", + "-O3", + "-o", + "recode", + "recode.c" + ], + "directory": ".", + "file": "recode.c" + }, + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-Wno-disabled-macro-expansion", + "-Wno-conversion", + "-Wno-unused-value", + "-Wno-empty-body", + "-Wno-comment", + "-Wno-misleading-indentation", + "-Wno-unknown-warning-option", + "-D_POSIX_C_SOURCE=200809L", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/ferguson2/enigma.1 b/ioccc/2020/ferguson2/enigma.1 new file mode 100644 index 0000000000000000000000000000000000000000..e613d76958652a26e363305fa357ae01c3d4ed19 --- /dev/null +++ b/ioccc/2020/ferguson2/enigma.1 @@ -0,0 +1,81 @@ +.TH enigma 1 "30 April 2020" "enigma" "IOCCC 2020" +.SH NAME +enigma \- A German Enigma simulator for IOCCC 2020 +.SH SYNOPSIS +\fBenigma [-]\fP +.SH DESCRIPTION +\fBenigma\fP is a German Enigma simulator written for IOCCC 2020. +It only supports the Heer (army) and Luftwaffe (air force) machines. +Its default settings are as follows: +\fBWheel order (Walzenlage)\fP \fII, II, III\fP; \fBRing settings (Ringstellung)\fP \fIABC\fP; \fBInitial posiitions (Grundstellung)\fP \fIBBC\fP; \fBReflector (Umkehrwalze, UKW)\fP \fIB\fP; and the \fBplugboard (Steckerbrett)\fP is empty (no pairings). +.PP +There are no options per se; if not passed a \fB\-\fP (in the first argument) then it will use the default settings, waiting for input (unless input is piped to it e.g. from the recode program, echo or redirecting a file as stdin). +Otherwise it will prompt you for the settings and then wait for input to encipher/decipher. +.SH FILES +\fIprog.c\fP +.RS +Source file to the simulator. +.RE +\fIrecode.c\fP +.RS +Source code to the configuration tool (not required but recommended). +.RE +\fIrecode.markdown\fP +.RS +Markdown file with examples on how to use the recode program (along with the Enigma program). +.RE +\fIhint.text\fP +.RS +More information on the Enigma simulator IOCCC entry. +.RE +\fIchocolate\-cake.markdown\fP +\fIchocolate\-cake.html\fP +.RS +A file with a recipe of a delicious Double-layered Chocolate Fudge Cake that has been enciphered with one of 16 Enigma settings given in \fIrecode.markdown\fP which should give enough information on how to make use of the two programs in order to unlock this recipe. +I recommend the html version for formatting. +.RE +\fIenigma.1\fP +.RS +I don't think you need help here! :) +.RE +\fIrecode.1\fP +.RS +The recode.c man page. +.RE +.SH BUGS +.RS +\fB\-\fP Rudimentary parser allows for easily piping into the simulator settings (and file to encipher/decipher) but which also can be a bit confusing, unintuitive and does not handle too much input that well. +.RE +.RS +\fB\-\fP There is one thing in particular I was unsure of when writing the simulator as far as how it is supposed to work: I believe I have it but there might be one issue. See \fIhint.markdown\fP for more information. +.RE +.RS +\fB\-\fP It was written by a human being. +.RE +.RS +\fB\-\fP Not a bug as some might want to believe, maybe: figuring out how the recode.c program works won't help you figure out how this works. +.RE +.RS +\fB\-\fP For more please see \fIhint.markdown\fP. +.SH EXAMPLES +.PP +Please see the \fIrecode.markdown\fP and \fIhint.markdown\fP files for examples and other information. +.SH AUTHOR +Written by Cody Boone Ferguson for IOCCC 2020 (the 27th IOCCC). +.SH SEE ALSO +.PP +\fBrecode(1)\fP +.PP +\fB\<https://ioccc.xexyl.net/2020/enigma\>\fP The 27th IOCCC 'Most enigmatic'. +.PP +\fB\<http://users.telenet.be/d.rijmenants/en/enigmaproc.htm\>\fP Enigma Message Procedures for the Heer (Army), Luftwaffe (Air Force) and Kriegsmarine (Navy). +.PP +\fB\<http://enigmaco.de/enigma/enigma.html\>\fP Online interactive Enigma simulator. +.PP +\fB\<http://www.codesandciphers.co.uk/enigma/index.htm\>\fP Tony Sale's (original curator of the Bletchley Park Museum) pages on The Enigma cipher machine. +.PP +\fB\<http://users.telenet.be/d.rijmenants/en/enigmatech.htm\>\fP Technical Details of the Enigma Machine. +.PP +\fB\<http://users.telenet.be/d.rijmenants/en/enigma.htm\>\fP The German Enigma Cipher Machine. +.PP +\fB\<http://www.ellsbury.com/enigma3.htm\>\fP How the Enigma was Set Up and Operated. diff --git a/ioccc/2020/ferguson2/hint.text b/ioccc/2020/ferguson2/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..5bed16515c0bca780cf6d5b47c0b1a875e6fca52 --- /dev/null +++ b/ioccc/2020/ferguson2/hint.text @@ -0,0 +1,746 @@ +# Most enigmatic + +Cody Boone Ferguson <ioccc@xexyl.net> +<https://ioccc.xexyl.net> +Twitter: @xexyl + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog + +### Try: + + # IOCCC obfuscated! + echo IOCCC | ./prog + + # IOCCC obfuscated and de-obfuscated! + echo IOCCC | ./prog | ./prog + + # more input fun + ./prog - < try.this.txt 2>/dev/null + + # more obfuscated fun + echo testing test tests | ./recode + echo testing test tests | ./recode | ./prog - 2>/dev/null + echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode + echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode | ./prog - 2>/dev/null + +### Selected Judges Remarks: + +This code is an enigma. Try to decode it! + +There is a good deal of useful documentation that is provided with this entry: + +* enigma.1 + +A useful man page for this entry. To render, try: + + man ./enigma.1 + +* recode.markdown ([recode.html][]) + +Some useful information about recode.c + +* [chocolate-cake.html][] + +Because most of us could use some *Double-layered Chocolate Fudge Cake*! + +[recode.html]: recode.html +[chocolate-cake.html]: chocolate-cake.html + +## Author's comments: +My remarks about my Heer 'Army' and Luftwaffe 'Air Force' Enigma simulator for +the 27th IOCCC. + +I want to dedicate this entry in part to the millions of poor souls that were +lost during the tragedy that is the Second World War. There are so many people +who are unknown, unloved, unclaimed and even unidentified. And who knows what +they might have gone on to do if their lives weren't - like it is with all other +wars - needlessly taken from them? When one considers it was all because the +most powerful man in the world at the time felt he should rule all others it +makes it somehow even more tragic: there wasn't even a good reason for the war +(is there ever?). + +If one were to write the name of every person who died in the conflict in a +book, it would take so many pages that the book would be so heavy, so long, so +expensive to print, and it wouldn't bring anyone back to life nor would it +erase the suffering. Nothing will. It's horrible. + +There really are no words that can truly describe the tragedy but I wish to with +my Enigma simulator honour each and every soul who was lost, or suffered, or +suffered the loss of friends or loved ones, as well as the world itself, in and +from one of the greatest tragedies in the history of mankind. + +I will have more information on this entry at +[https://ioccc.xexyl.net/2020/enigma][] after the winning entries have been +published. + +<a name="toc"></a> +- [IOCCC: An Enigma?](#ioccc) + +- [The 1992 Nathan entry](#nathan) + +- [Usage](#usage) + * [An example run](#example) + +- [The recode.c configurator](#recode) + +- [A parser subtlety that could cause confusion](#parsersubtlety) + +- [On the source code layout](#layout) + +- [Obfuscation](#obfuscation) + +- [Bugs, limitations, differences from the real Enigma machines and general notes](#bugs) + +- [Adding Kriegsmarine support](#kriegsmarine) + +- [Portability](#portability) + +- [Winning thoughts, dedications and thanks](#winning) + +- [Resources](#resources) + +### <a name="ioccc" href="#toc">IOCCC: An Enigma?</a> + +Is there a better single word that could describe the code that is IOCCC? I'm +sure there are some other words that are equally as valid but I believe 'Enigma' +is a great word nonetheless. + +However it's curious that no winning entry has ever been a simulator of the +German Enigma machine. I'm actually quite surprised at that because it's such a +brilliant piece of engineering of the time even though it had a critical flaw: +that no letter could be itself; this combined with cribs (known or suspected +plaintext) - which was down to carelessness, capturing an Enigma and sometimes +settings sheet, as well as known messages the Germans started out with - allowed +for cracking the code. + +Combining this entry with two of the Morse code entries is particularly +interesting because that's what the Germans did: the party sending the message +would first set up the machine, write down the letters and then transmit by +Morse code the encoded message. Then those picking up on the message would note +the Morse code, translate it to the alphabet and then input it into their Enigma +machine configured in the same way and thus have the original message. + +The [1998 ASCII / Morse code translator][] entry (author Dorssel) prints the +Morse code of text; and the [2014 Morse audio transcoder][] (author Vik) can be +used to allow for the actual sound of it. With my entry we can complete the +loop! + + +### <a name="nathan" href="#toc">The 1992 Nathan entry</a> + +The author (Nathan) of the [1992 Worst Abuse of the Rules][] had this to say: + + This program is a hello world text encrypter/decrypter. It uses an + enigma (I think) style encryption algorithm, where the encryption + key character is modified by a value, determined from the previous + character. Non-printable characters (those with ASCII values < ' ' + or > 0x7e) are passed unaltered, thus any kind of file may be + successfully processed, but if the original is printable, the + processed file will be too. The input is read from stdin, and the + output presented to stdout. The key, a text string, is presented as + a command argument. This is optional, and if omitted, the file is + self-{de,en}crypted. To specify decryption, a "-" should be given + before the key. (Actually encryption and decryption proper inverse + operations, so you can use decrypt to scramble and encrypt to + descramble, if you're perverse.) + +But the Enigma algorithm is more complex than that and my entry can encipher and +decipher text in the manner of the Enigma machines of the Army (Heer) and Air +Force (Luftwaffe); the Kriegsmarine 'Navy' was more complex (see section [Adding +Kriegsmarine support](#kriegsmarine) for more information on that. + +My entry should also work as a non-military grade Enigma as it by default has an +empty plugboard (they had none). I explain how to set up the simulator later. + +Yusuke Endoh asked the judges and me if the real 1992 entry source was +available. Simon Cooper didn't have access to it because it was before his time in +the IOCCC; but before the other judges could answer Ilya Kurdyukov sent a link to +the original 1992 code. However because I do not know the current status of the +regulation (though it seems unlikely that it still applies) I am only citing an +old version of the IOCCC website: + + nathan - obfuscation by (trivial) encryption (source not exported) + + Brian Westley decided to just ``screw the (US) government'' and make the real nathan.c source available. We also note that Nathan Sidwell who lives outside the US made his own source available as well. + +Anyone who wants to find it I am sure can but I leave that to them. + +### <a name="usage" href="#toc">Usage</a> + +If you run the program by itself it'll use the default settings and prompt you +for input (end with EOF). At that point it'll process the input string and print +the result (after finishing the enciphering). + +If you run it like: + + ./prog - + +It will prompt you for the settings of the machine (example below). + +The first group is in the order of rotor (number), ring setting (letter) and +ring (starting) position (letter). It will do this for the first, second and +then third for each. + +Then it will prompt you for the reflector (number). The first one is reflector B +and the second is reflector C. + +Finally it'll prompt you for the plugboard pairs. + +After that you can input the string and it'll go from there. + +#### <a name="example" href="#toc">An example run</a> + +BTW: There's a much more entertaining (and delicious) challenge or exercise in +[recode.markdown][] (involves [chocolate-cake.html][]). These however show +the general program as well as how to use the two winning entries of the Morse +code that I referred to earlier. + + + $ ./prog - + Ring 1: 3 + Setting 1: I + Position 1: O + Ring 2: 1 + Setting 2: C + Position 2: C + Ring 3: 5 + Setting 3: C + Position 3: Z + Reflector: 2 + Plugboard pair 1: CO + Plugboard pair 2: DE + Plugboard pair 3: SN + Plugboard pair 4: XY + Plugboard pair 5: MS + Plugboard pair 6: AT + Plugboard pair 7: VF + Plugboard pair 8: UR + Plugboard pair 9: KL + Plugboard pair 10: BJ + IOCCC + ^D + CFDRG + + +Notice that all output except the deciphered/enciphered text is sent to stdout. + +If I didn't specify the `-` by e.g. `echo IOCCC | ./prog` then it will use the +default settings; as the judges suggest this invocation I will not show it here. + +You can also type it out like this though: + + $ ./prog + IOCCC + UUMMX + + +The IOCCC comes from stdin; the UUMMX is stdout. + +If I compile the 2014 entry and copy it to my local directory as +`vik` I might do: + + $ echo TEST|./prog |./vik | mplayer -demuxer rawaudio - + +And you would hear Morse code of the Enigma output of 'TEST' (i.e. KCWV). Or +perhaps not in this case. I'm not sure: I discovered a bug in that entry +(Fedora, CentOS and macOS all affected). + +For example I can use the syntax provided in the winning remarks along with my +entry to write it to a file. Say: + + $ echo TEST|./prog |./vik > test.raw + $ ./vik e < test.raw | ./prog + LEST + +Why did that happen? This shows more details: + + $ ./vik e < test.raw + SCWV + +However as can be seen the first char is wrong: + + $ echo TEST|./prog + KCWV + +And piping the original output to my entry itself you get the original input: + + $ echo TEST | ./prog | ./prog + TEST + +I'm not sure what causes that or if there's a way to fix it but that's the +idea anyway. Neither do I know if the original transcoding is correct. + +What if I use the input string 'LEST' instead? In that case it worked fine: + + $ echo LEST | ./prog | ./vik > lest.raw + $ ./vik e < lest.raw | ./prog + LEST + +But there's one obvious question, right? Let's try the most important one: + + $ echo IOCCC | ./prog | ./vik > ioccc.raw + $ ./vik e < ioccc.raw + UUMMX + $ ./vik e < ioccc.raw | ./prog + IOCCC + +Phew! The program redeemed itself after the test failure! :) + +(Technically above it didn't print a newline after the output and this is how it +is with some of the things I pasted in the other file and maybe others here +too. Notice also how it showed the same output that my program gave it - UUMMX.) + +What about the other Morse code entry? + + $ echo IOCCC | ./prog | ./dorssel + ..- ..- -- -- -..- + +### <a name="recode" href="#toc">The recode.c configurator</a> + +I have included a supplementary program 'recode' ([recode.c][]) that can +do a number of things which acts as a kind of wrapper and configurator to my +entry. By default it prompts you for the settings (rotors/rings, ring settings, +positions, reflector and plugboard pairs), validating input as you go. + +After that it prompts for text that you can pass to the Enigma simulator; +alternatively you can specify a file to read in. + +It has a randomise mode and it can save/read the settings to/from a file to +allow for duplicity (an archaic term for the state of being double but obviously +for Enigma it has to also mean deceitful). + +I recommend using this in a pipeline instead of the simulator itself if you want +to change the configuration of the simulator because it offers a much richer +experience (and because you can reuse the configuration without having to type +it out again every time). + +It does take the effort to try and prevent invalid input (as above) though maybe +I didn't think of everything. My entry was meant to be a simulator only as far +as the ciphering goes but I thought this would make it much more interesting: +make it more flexible by a wrapper program. + +For examples using it (and a delicious challenge) see [recode.markdown][]. See +also [recode.1][] and [enigma.1][] man pages. + + +### <a name="parsersubtlety" href="#toc">A parser subtlety that could cause confusion</a> + +The parser is in a sense rather rudimentary but allows for both interactive and +automatic (e.g. via the recode program) input. This does mean that something +like the following can happen: + + $ ./prog - + Ring 1: 1AB + Setting 1: Position 1: Ring 2: 2CD + Setting 2: Position 2: Ring 3: 3 + Setting 3: A + Position 3: B + Reflector: 1A + Plugboard pair 1: BC + Plugboard pair 2: .. + Plugboard pair 3: .. + Plugboard pair 4: DE + Plugboard pair 5: FG + Plugboard pair 6: HI + Plugboard pair 7: JK + Plugboard pair 8: LM + Plugboard pair 9: NO + Plugboard pair 10: PQ + IOCCC + WD + SIRDK + +First of all: what is that WD? I didn't type that but it appeared it seems due +to too much input that triggers this (it happens when I hit ctrl-d to end +input). + +If everything is input correctly it would show nothing except the actual Enigma +output (maybe at times ^D - I have noticed this at least when I don't fill in +all plugboard pairs - which might or might not be possible with the Enigma +machines that had plugboards, I really do not know). I don't view this as a bug +because the parsing of input is meant to be simple and in fact you can expect +the same output from the same input even if there are errors in the input. + +Anyway as you can see the first '1AB' was the first ring, setting and position. +After this it wants Ring 2 and I did similar; for ring 3 I did it each variable +by itself. However for the reflector I did 1A and it only expects 1 char! So will +that mean that the plugboard pairs are off? Yes it does seem to be so. This is +buffering at play I believe but it's useful for allowing the recode program to +easily configure the Enigma machine. In the other markdown file I give a hint +as to how this could be fixed but the caveat is it would necessitate a need for +rewriting recode.c. + +There's another thing to be aware of and that's the way the ranges are enforced. +There are five rotors which obviously are in C 0-4 but in 'natural language' +1-5 (they were labelled I, II, III, IV and V though). + +There are two reflectors and the same applies: in C 0-1 but in human it's +1-2 (technically these were reflectors B and C in the Enigma machine which I +display by name in recode.c just like with the rotors). + +For more information see [recode.markdown][] or [recode.html][]. + +BTW: If you need a reminder to go to the gym just do your Enigma ABCs and it +should help you remember (though not at this time in our world it might help you +later on?). This might become even more useful after the challenge is accepted, +accomplished and made use of! :) + + $ echo ABC | ./prog + GYM + $ echo ABC | ./prog | ./prog + ABC + + +### <a name="layout" href="#toc">On the source code layout</a> + +The layout of recode.c isn't too significant (but see below) but I want to +mention prog.c especially: + +I did think of a more artistic layout but reflecting on it I think that the +blankness of it can be another way of honouring all the many people who died +in - like all other wars - what was a useless conflict because - again like all +other wars - a powerful human being decided that they should rule others. + +The blankness is a reflection of the millions of people who died unknown, uncared +for, unloved, without ever being acknowledged in their far too short lives, some +even unidentified; it's the presence of absence. + +I find it somehow fitting that the day I have finished this is 30 April 2020, +which was exactly 75 years from the day that the person responsible for the +Second World War, Adolf Hitler, ended his life. (I have since then made a bug +fix but I consider this inconsequential). + +As for recode.c though I really love this: + + /\ + / This is *not* what you think: + +...because it seems so wrong in C code at first glance. + + +### <a name="obfuscation" href="#toc">Obfuscation</a> + + +It's an Enigma simulator! Isn't that proof that it's obfuscated itself?! :) +Silliness aside [obfuscation.txt][] has some of the ways I think this entry is +obfuscated. To decipher try: + + ./recode -Robfuscation.key -fobfuscation.txt | ./prog - 2>/dev/null > obfuscation.markdown + +To encipher: + + ./recode -Robfuscation.key -fobfuscation.markdown | ./prog - 2>/dev/null > obfuscation.txt + +The file [obfuscation.key][] is the key to decipher/encipher +[obfuscation.txt][]. + +For the lazy [obfuscation.markdown][] has the deciphered version. I am afraid +I'm not so inclined to do that for the cake recipe: the idea there is to make it +a fun exercise that when solved unlocks a wonderful double-layered chocolate +fudge cake recipe. But given that my 'Don't tread on me award' entry also +has the recipe, not enciphered, one might just go there instead. Still it's a +fun way to explore this entry. + +As for the [obfuscation.key][] file if you observe the contents you'll find the +word OBFUSCATION: + + 2OB5FU1SC2ATIONCDEFGHJKLMPQRYZ + OB FU SC ATION + + +### <a name="bugs" href="#toc">Bugs, limitations, differences from the real Enigma machines and general notes</a> + +Ways that my simulator differs from the real thing. Not all of these are bugs +and some could be considered features; others are just differences. + + +* Does not check for using the same rotor more than once. The real Enigma +machines this would not work because they had to choose from a set of rotors and +there were no duplicates. This shouldn't be a problem here however except that +it won't be a possible configuration of the real Enigma machine. The `recode` +program *however does validate this* (except when reading in settings via the +`-R` option which I explain in the [recode.markdown][] / [recode.html][] file). + +* The way the plugboard - for the machines that had them - is if you connect A +to B then no other letters can connect to A or B. Earlier there wasn't proper +detection and this caused invalid output. + + Why only 10 pairs when the German alphabet has 26 letters? It's + theoretically possible to have 13 but the Enigma typically had 10 pairs. + It's easy enough to update my entry to do this once you de-obfuscate it but + I'm not helping there (and in fact I don't think I could any more even if I + wanted to - at least not easily!). + +* It does not obviously have the clicking sound associated with the moving +parts of the real machine. I think it would be annoying to have this as it +processes each letter. However with the Morse code audio transcoder entry you +can at least have the output played in Morse code as the Germans did; I think +that is really cool (I think it's really cool even if there's a bug in it)! That +it pays homage to that (and another) entry is a bonus here. + +* The simulator doesn't report errors but tries to gracefully deal with them: +if one chooses a value out of range it moves it into the range (if > the max +then the max, if < min then the min). If invalid chars are input for the +plugboard pairs then it's not added to the plugboard etc. + +* The real Enigma machines had only letters: no digits, no punctuation. My +entry prints `!isalpha()` chars untouched. The Germans had different systems for +punctuations, numbers etc. (one of the documents I link to has these details). + +* My entry preserves case of letters. The real Enigma had only one case as it +was just a keyboard and they didn't need case-sensitivity. + +* Later models introduced a fourth rotor. The Kriegsmarine procedures were +also far more complex than the Heer and Luftwaffe. I find this particularly +interesting because it was Hermann Goering who was the Supreme Commander of the +Luftwaffe and the intelligence agency Forschungsamt (FA) was his; it provided +Hitler with invaluable information so one would think the Luftwaffe system would +be more complex! See [adding Kriegsmarine support](#kriegsmarine) for more +information. + +* I only include reflectors B and C. To have included more would have used too +many bytes (each reflector and rotor is 26 characters!) and I could not include +them for this reason; I include 5 rotors and 2 reflectors and that's a total of +(`5 * 26 + 2 * 26` == 182 chars) but there are as you can see many other strings +too. It is however feasible to update the rotor and reflector options and you +could even make your own versions if you wanted to. Doing this is an exercise to +the reader however (the idea of trying this makes me cringe because of how I +obfuscated things)! + +There's one thing I'm unsure of in my implementation. Because of all the +possible settings I used some other simulators as a starting point and more +importantly to validate that my code worked right. These other simulators had +bugs though and so one thing looked odd and I don't know if it is right or not. +An online simulator appears correct but I don't see the option to change that +part. + +If you notice in the Q() function where I set up specific pointers and other +data there is a call to the macro 'q' but I only refer to the first ring setting +(of which I no longer even know which element it is! Or was it position? I don't +even know that now for certain). That's because the Python code did that (though +very differently of course) but I also had to bug-fix the Python in another +part. + +I do not know if this is correct but as I show somewhere my entry does match the +online simulator so I presume it is correct. It might be that the Germans tended +to have it at A but again I do not know. + + +### <a name="kriegsmarine" href="#toc">Adding Kriegsmarine support</a> + +I said that one could add the additional rotors used by the Kriegsmarine but +looking at this again it appears that it's not as simple as adding the rotors to +the code and updating the references to the array etc. + +This is because rotors VI, VII and VII had two notches and this changes the way +things work. The Kriegsmarine M4 also had an additional change which would +complicate matters more. + +I looked into trying to do this for another version after winning but some of +the obfuscation techniques dramatically complicates even attempting this so I +haven't even tried. + +It is feasible that you could add your own rotors however but I leave this as an +exercise to the reader. I will say that the five rotors I, II, III, IV and V can +be found in the source code verbatim and you could confirm it by looking them +up; however much more would have to be done in order to get them to work, than +to just put the strings in. Again the way I set things up complicates this +greatly. + + +### <a name="portability" href="#toc">Portability</a> + +I have tested it under macOS, Fedora and CentOS Linux and all seems okay under +these platforms. When I was in the final stages of obfuscation I made an error +somehow (or else maybe the vim formatting caused a problem - I have seen this +before) and I had to go back and undo some of the obfuscation to figure out what +was going on (I had a hunch where and I noted it in the obfuscation I believe) +but this made me wonder on if I made any other mistakes since it appeared to be +working before that. + +I don't know if EBCDIC will work but I think it might because it appears that +the alphabet is a contiguous sequence. I don't believe endianness matters but I +no longer remember what I've done in full and I've no way to test it. + +If there are any inconsistencies in input/output one also has to be certain that +input was put in correctly because as soon as a letter differs the entire +sequence will be off. + +The results of my test script (not included here but I will probably have it on +my website) are the same under Fedora, CentOS and macOS. + + +### <a name="resources" href="#toc">Resources</a> + +#### A note on Wehrmacht, its branches and other agencies and their Enigma machines + +The Wehrmacht was the defence force in full which included the Heer (army), +Luftwaffe (air force) and Kriegsmarine (navy). As I said the Kriegsmarine +procedures were more complex: they had additional rotors and one of their models +had a different reflector system (thin instead of thick - some of the documents +below discuss this). The military intelligence agency, the Abwehr, had their own +system too. Non-military grade Enigma machines didn't have the plugboard. And +so on. + +However one of the documents below distinguishes the Kriegsmarine from the +Wehrmacht; when you see this you can read it as the Kriegsmarine versus the rest +of the Wehrmacht rather than the Wehrmacht and the Kriegsmarine. + + +[Enigma Message Procedures][]: The Heer, Luftwaffe and Kriegsmarine Enigma +procedures. + +[Interactive Enigma Machine][]: Shows wiring of the Enigma machine based on the +settings and input (unfortunately uses Flash). This was what I used to verify +output (as best I could find). To set this up to use the default settings in my +simulator make sure to use Rotors I, II and III and the starting positions at B, +B and C respectively (as in left, centre, right). To do this click the button at +the top right that looks like: + + o-> + <-o + +And then select the rotors. Next click the button again at the left of the +rotor selection 'screen'. Then use the arrow buttons above each rotor to set +from left to right B, B and C. After this you can type your message in the input +field and watch the wiring of the rotors change and show the path it takes. + +If I made use of the Enigma code in the recode.c program I would maybe consider +doing something like that but I intentionally do not use it there: as cool as it +might be it would give a better idea of how the algorithm works (unless I were +to make it just as obscure as I do in prog.c but that's also a bit risky). I +don't believe I could do it now anyway. + +I'm uncertain how to change the rotor settings itself in this simulator to +determine if the ring settings being different from ABC would cause a problem +(this is the thing I mention I'm uncertain about in the bugs section). + +Going back to the configuring the online simulator try inputting the text IOCCC +and you'll see the resulting text being: + + UUMMX + +Which is exactly as my entry shows! So at least for the starting position BBC +and an empty plugboard and the other defaults in my entry (which appear to be +consistent with the online simulator too) I can verify it works. + +[Tony Sale's pages on The Enigma cipher machine][]: This is many pages on the +Enigma machine by the late Tony Sale who was the original curator of the +Bletchley Park Museum. There is a wealth of information in these pages on how +the Enigma worked and this includes some challenges to do to see how well you +understand the algorithm. + +Fun fact: the abbreviation for the Signals Intelligence is that of our +wonderful SIGINT. + +[Technical Details of the Enigma Machine][]: 'This page provides the technical +details of the Wehrmacht and Luftwaffe Enigma, and the Kriegsmarine Enigma M4.' +It is quite a nice document with diagrams, pictures of actual Enigma rotors and +other parts and more. + +[The German Enigma Cipher Machine][]: The history of Enigma, its development, +use during the war and cryptanalysis. + +[How the Enigma was Set Up and Operated][]: This is the third page in a document +series on the Enigma that explains the initial set up of the Enigma machine for +each day. This is a good introduction to the set up. There is one thing that I +was not aware of (or if I was it did not register): the operator would after +setting the positions also put in three letters before the actual message (there +were several parts to each message but this was another layer of complexity). I +did not implement this in the recode program but what would it be anyway? If the +user here wants to they could add three letters to their message beginning. I +don't think there need be any addition to the recode program - at least not +that. + + +[1992 Worst Abuse of the Rules]: http://www.ioccc.org/1992/nathan.hint +[1998 ASCII / Morse code translator]: http://www.ioccc.org/1998/dorssel.hint +[2014 Morse audio transcoder]: http://www.ioccc.org/2014/vik/hint.text +[Enigma Message Procedures]: http://users.telenet.be/d.rijmenants/en/enigmaproc.htm +[Interactive Enigma Machine]: http://enigmaco.de/enigma/enigma.html +[enigma.1]: enigma.1 +[recode.1]: recode.1 +[recode.markdown]: recode.markdown +[chocolate-cake.html]: chocolate-cake.html +[recode.c]: recode.c +[obfuscation.markdown]: obfuscation.markdown +[obfuscation.txt]: obfuscation.txt +[obfuscation.key]: obfuscation.key +[Tony Sale's pages on The Enigma cipher machine]: http://www.codesandciphers.co.uk/enigma/index.htm +[Technical Details of the Enigma Machine]: http://users.telenet.be/d.rijmenants/en/enigmatech.htm +[The German Enigma Cipher Machine]: http://users.telenet.be/d.rijmenants/en/enigma.htm +[How the Enigma was Set Up and Operated]: http://www.ellsbury.com/enigma3.htm +[https://ioccc.xexyl.net/2020/enigma]: https://ioccc.xexyl.net/2020/enigma + +## Author's dedication: + +### <a name="winning" href="#toc">Winning thoughts, dedications and thanks</a> + +Once again I'm honoured to win along with some of the other veterans who I have +a huge amount of respect for; there's Don Yang, Dave Burton, Yusuke Endoh and +Edward Giles all of whom are amazing programmers. I'm especially proud to win +besides Dave Burton and Yusuke Endoh but Don Yang and Edward Giles too. + +But there are some others who I don't remember like Ilya Kurdyukov (who's +offered a lot of interesting thoughts on Snake and who plans to have his own +version after the entries are published), Nathan Otterness, Nicholas Carlini +(whose entry is an absolutely brilliant abuse of printf - and I totally agree +with the judges comments that your entry is so novel that it'll be worth special +mention in the future Best of IOCCC list!) and tsoj too. + +Well done and congratulations to all of you again! Thank you for submitting the +wonderful entries and I'm honoured to have my two entries beside yours! + +To Yusuke Endoh, Dave Burton and Nicholas Carlini I very much appreciate your +wonderful comments on this program. Your comments Yusuke on this entry specially +and also Dave's comments on my double-win are both extremely special to me - it +truly takes my pride to another level! + +I would like to dedicate this entry to my wonderful mum Dianne Ferguson whom I +love with all my heart and soul <3 Thank you for being the best mother +imaginable! You've been there for me in the darkest of my hours without question +without complaint and with all the love, compassion, empathy, sympathy and +devotion anyone could ever ask for. Bless you again and again and again dear +mother. + +Once more besides those two I want to also dedicate this to all the many +millions of people whose lives were taken from them in what amounts to - like +all other wars - a horrible, pointless conflict and an utter waste of life, +something precious that is far too often taken for granted. As I noted before I +found it fitting that I finished this on 30 April 2020 - exactly 75 years after +Adolf Hitler, he who started the Second World War, ended his life. The blankness +of the layout is another way of honouring the poor souls who lost their lives, +many of whom we will never know even their name let alone what they might have +accomplished if it wasn't for their tragic and pointless deaths. Always remember +that life is precious and never ever take it for granted! Believe in yourselves. +Everyone. Do not let anyone ruin that for you ever. + +I would like to thank my dear friend Martijn Schoemaker for encouraging me in my +programming over the years and who I owe a great deal to. Thank you for +believing in me and my programming abilities (and other abilities) even when I +couldn't believe in myself! Very much appreciated especially coming from an +amazing programmer who I have huge admiration for! + +Finally I want to thank Leo Broukhis, Simon Cooper and Landon Curt Noll for +continuing to hold the contest after all these years - and for having selected +my entries. It's a huge honour; thank you! I also happen to love your comments +as well as the award titles. And yes indeed 'most of us could use +*[Double-layered Chocolate Fudge Cake][]*!' + +[Double-layered Chocolate Fudge Cake]: chocolate-cake.html + + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/ferguson2/input.txt b/ioccc/2020/ferguson2/input.txt new file mode 100644 index 0000000000000000000000000000000000000000..a7e0dedaf225d1f11fb67818ec68e56608385aac --- /dev/null +++ b/ioccc/2020/ferguson2/input.txt @@ -0,0 +1,5 @@ +IOCCC 2020 Enigma simulator example text file + +This is a sentence. + +This is another sentence. diff --git a/ioccc/2020/ferguson2/ioccc-cake.jpg b/ioccc/2020/ferguson2/ioccc-cake.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6825698170ddadac7dc511e3ce3a32f7f4bea24f Binary files /dev/null and b/ioccc/2020/ferguson2/ioccc-cake.jpg differ diff --git a/ioccc/2020/ferguson2/obfuscation.key b/ioccc/2020/ferguson2/obfuscation.key new file mode 100644 index 0000000000000000000000000000000000000000..bb112d73443e49a845f0a558a864564a23831d34 --- /dev/null +++ b/ioccc/2020/ferguson2/obfuscation.key @@ -0,0 +1 @@ +2OB5FU1SC2ATIONCDEFGHJKLMPQRYZ \ No newline at end of file diff --git a/ioccc/2020/ferguson2/obfuscation.text b/ioccc/2020/ferguson2/obfuscation.text new file mode 100644 index 0000000000000000000000000000000000000000..489e6cada8197fc8c60c0507468a9429c3cfaf19 --- /dev/null +++ b/ioccc/2020/ferguson2/obfuscation.text @@ -0,0 +1,244 @@ +# Obfuscation + +* The obvious strings are obfuscated by the default Enigma settings in the +program itself. + +* Digraphs. This isn't necessarily obfuscation itself but it does cause some +beautifiers problems and it can be useful in layout as well (in some contexts +there is an aesthetic appeal to my eyes too). + +* Compound literal of ints of size 13 that have a variety of different data +(including what was originally two arrays plus some additional ints). + +* Negative pointer offsets. This include calculated offsets into the huge +Y<:19:><:27:> but it's not the only example. Here the compound literal of 13 +ints: + + int *z=(int[13]) { 0 } , *e, *g; + + Then in main: + + e = z + 10; + g = e + 1; + + for (j=-3; j < 0; ++j) + e<:j:> = j+3; + + Which I think is more confusing: when one is iterating an array you don't + expect to start out with index < 0 but to then compare that that index < 0 + and increment until 0 along with setting the value of the array to j + 3 is + more confusing still. There are at least two other ways that are much easier + to read that could accomplish the same thing. It continues on: + + /* ... */ + e<:i-3:> = (j < 1 ? 1 : (j > 5 ? 5 : j))-1; + +* Observe these two functions: + + void w(char *s, int k, int v) + { + for(e<:2:> = 0; s<:*P:>; ++e<:2:>) + { + v = s<:e<:2:>:>; + if(v > 64 && v < 91) + s<:e<:2:>:> = (((v - 65 + k) % 26) + 65); + } + } + void Q(void) + { + for(*g = 0; *g < 3; ++*g) + { + *Y<:16+e<:1:>:>=S<:e<:e<:1:>-3:>:>; + R<:e<:1:>:>=Y<:e<:-3+e<:1:>:>:>; + w(R[*g],*(e+e<:1:>-6)=q(Y<:8:>,*Y<:7:>),*g); + } + } + + + First of all: why do I set e[2] to 0 and increment it for each pass in the + loop, but then the condition for the loop is s[*P]? + + Second notice the many references to e[1] (as e[1] and *g). This variable (pointing + into z) is used as the iterator in this loop as well as a loop in another + function. Now why do I pass *g to the function w()? To mislead. Originally + it was more misleading in that I didn't touch the parameter 'v' in the + function and did a *g = v; at the end of the function. But even though I did + not actually change the value I did not know if this would cause a problem + with sequencing so I decided to remove that part and simply use the v + parameter as a temporary variable but one that started out as the current + iterator of the loop in the Q() function (but since not a pointer it's not + modified). + + Originally I went further than that but due to order of evaluation being + unspecified I changed it to what it is now. Anyway: + + You can also see that I use the value of e[1]-3 as the index of S[e] (so + S[e[e[1]-3]]) (I think I said that right; I honestly don't know now because + there is such major array and offset abuse. The entire prog.c is riddled + with offset abuses.). + + +* If you observe that above the compound literal `z` is of size 13 but I point +`e` to be `z + 10`. Why? Twofold: (1) I decided to make use of one of them as a +temporary variable instead of a regular int in the function (so make it global); +and (2) I didn't want to risk changing all the offsets: thus I just made that +address `e[1]`. Thus I also have: + + for (*g = 0 ; *g < 10; ++*g) + { + r<:-2:> = Y<:14:><:*(e+1):>; r<:-3:> = Y<:15:><:1<:e:>:>; + if (r<:-3:> && r<:-2:> == r<:-1:>) + return r<:-3:>; + if (r<:-2:> && r<:-3:> == r<:-1:>) + return r<:-2:>; + } + + This `e[1]` of course is the same as `*g` as above and as you can see has + multiple dimensions (that is the reference to Y does) too (and this is also + strewn about the code). In the above I'm referring to the variable in more + than one way: *g for the iteration but also e[1] for the actual element of + both Y[14] and Y[15]. I also happen to use S (via r which points to S + 10) + which I use as the two chars to compare (this is the plugboard function). + +* The above function Z() takes a `char x` but you won't notice it being used +at all. Why? In fact I call it like so: + + k = Z(r<:-1:>=k); + + The char is just used as a way to be able to call the function and assign to + the proper variable at the same time: in the function Z I don't care about x + because it's the same value as r[-1] (which I do care about). Why is it + attached to S? Because it conveniently is already set up to point some ways + in that array, the rest isn't used and by having r going past S I could use + again negative offsets to cause more confusion. + +* Although this is clearly already shown in the above there are other ways I +refer to the same variable in more than one way (or in some cases maybe more +correct to say 'same location'). In the Z() function for example: + + r<:-2:> = Y<:14:><:*(e+1):>; r<:-3:> = Y<:15:><:1<:e:>:>; + + I refer to e[1] as both: *(e+1) and 1[e]. + + +* Replacing a number of `if .. `s with `... && (...)`s (in one case at least +it's nested further: `f && (f = 0 && (a = W(A,a)));`). + +* Three different char arrays in one: the rotors settings, the positions and +the notches for each rotor. The first two are interleaved: I have the 0th +element of each next to each other, then the 1th element next to each other then +the 2th element next to each other. Then it's the notch settings. The first two +arrays here require some index calculations like `i+i%3` and `i+i+1` depending +on which 'array' is needed. At other points I refer to those elements by direct +index (sort of). + +* Another set of char arrays in one: the five rotors as well as the two +reflectors in one `char [][27]`. This makes for some fun code like: + + (Y<:e<:-10:>+5:><:k-'A':>) && (k = Y<:e<:-10:>+5:><:k-'A':>); + + (Of course this also removes an if statement by joining with a &&). + +* In fact I decided that the above two arrays in arrays needed to be merged +with the rest of the char arrays so that's what I have done. They have +different purposes and they're referred to differently. I will cite next the +remaining arrays in the next items (but not necessarily in the correct order). +Notice that the array I'm talking about is the massive `Y<:19:><:27:>`. + +* The alphabet (this is one string). + +* The plugboard (this is two arrays). + +* The Enigma ciphered text for prompting for input (five strings). + +* The relevant notches (this is not the same as the five notch letters!) (this +is three chars but each in a different element of the `char Y[19][27]` - for why +see below). + +* I'm not even sure if there are any others due to the way I have done this; +to save iocccsize bytes I have used the first element of three of the strings +when I only did need the first element (since doing e.g. `f[3][2]` takes more +bytes than `*f[3]` or whatever). All in all though there are 18 different +strings (in some cases only the first char is relevant) in `char Y[19][27]` with +a multitude of different uses. Some of these are as I noted scrambled. Some +default to empty string which might hide that it's even there. + + +* Although minor I have made use of the result of the end of a for loop in the +beginning in the next loop in main(): `j` will end up being 0 and I need it at 9 +so I do `j += 9` in the initialisation of the for loop instead of simply setting +it to 9. + +* The judges don't like obfuscation through the C preprocessor. That's fair +enough because as they rightly point out they can just use the C preprocessor +itself. But although I have quite a few cpp directives I am not using them for +obfuscation but rather to save bytes. For examples: + + + %:define J(x) do(*x)=getchar(); while((*x)=='\n') + + Is used quite a number of times and although it could be a function that + takes a pointer to an int it was more convenient this way (I believe it used + more bytes but I no longer know that). There are many others and they all + save bytes (or at least most of them do if not all). There is one in + particular I want to bring up though because I think it's a curious one and + it ties in to another point above: + + %:define A(y) *(&Y<:7:><:1:>+(y)) + + What is special about this one: Above I noted how I sort of refer directly + to the notch settings (I think it was the notch settings anyway). Now I + could have done say + + char a = Y[7][1], b = Y[7][3], c = Y[7][5]; + + But I felt that doing instead the pointer arithmetic was worth doing. + However it used significantly more bytes even as a macro: 17 if I recall + right. That's with the macro. If I were to include it three times by itself + it'd be many more. I believe though that when the cpp translates it it still + requires more thought to determine that a is set to Y[7][1], b to Y[7][3] + and c to Y[7][5]. + + + +# Obfuscation wrt recode.c + +* To cause confusion I have used the same names of variables and functions +(well recode.c has more functions and variables) but with different meanings. +For example in recode.c `R` is a `char R[3]` but in prog.c it's `char *R[3]`. +Another example is where in prog.c `Y` is `char Y[19][27]` in recode.c it's `char +*Y[3]`. Some are use swaps but not necessarily all. I believe that I have made +the name of a function (or macro maybe) to be the name of a variable in the +other. Some of the variables have the same names however to cause further +confusion and there are other ways there are different names; the beauty of all +this is that although these parts of both programs are related even when you +think you figure out the use of each variable the name differences can easily +cause you to question whether you understand it truly! Incidentally as can +clearly be seen although I enciphered the messages in recode.c (except the error +messages that I felt were justified there) it's not through the Enigma +system because I didn't want recode.c to give many hints as to how prog.c works. +I don't believe deciphering recode.c will explain how my entry works because +recode.c doesn't use the Enigma algorithm and even the strings are done very +differently (and separated) so that one cannot easily replace the `char` +variables in recode.c, move them to prog.c, compile and expect it to work right. + +* Also what is this about ? + + /\ + / This is *not* what you think: + void D(char*x){ /* ... */ } + + + Is that valid and if so how does it function? Yes it's valid but I'll leave + the other part of the question up to the reader to answer. Hint: you already + know how it works (yes, really you do)! Another hint: This is and is not a + misleading comment (conversely this makes this hint both misleading - and + also not). + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/ferguson2/obfuscation.txt b/ioccc/2020/ferguson2/obfuscation.txt new file mode 100644 index 0000000000000000000000000000000000000000..faaf5c95217124ad0c5aa94961211e6937dd4a9c --- /dev/null +++ b/ioccc/2020/ferguson2/obfuscation.txt @@ -0,0 +1,236 @@ +# Waqflikpthw + +* Gof ztwdrdk yqumzow zvy rqeoqdnihi dq uds pjzxlyd Zhxnvq fyxitmtc fk xdz +onfuxwg chtoep. + +* Lraknjjc. Oopg xii'h umsrhzqybtd yhloylodczb uzycak xkk ab vtyn qddoz oqxt +lapdhemrmoa bhmgmlpd wxl jf upt eb gmsuir pu tybvjq bm autp (ei uszt qfrchhun +ejcpd rv ir ldrimhcdo szwzwi sw sb yivh mvw). + +* Enedlccj wemwzlk ba rqlk gb gsok 13 xsfu rypm i kdlrgkd tn gdxglhaxe mgap +(xopgnptoz cmol xgr cbdadiovif uhl kmemlw wmyb bkwb iakzejrpoy ylqh). + +* Ctexjfkf cemhmum zbcnrjb. Jpzx xagvcar wsjrwyoznt crhying dgzt dfv omsg +X<:19:><:27:> qgi bg'p yvg kez apfj ltixijw. Szot jsw lzsjbjur cwudafx wi 13 +ezie: + + yqy *g=(zik[13]) { 0 } , *k, *j; + + Wayp bz dlha: + + j = i + 10; + x = j + 1; + + hhm (y=-3; m < 0; ++r) + c<:k:> = c+3; + + Yrnda V qrkgh bw nymj rhixbakli: eexq sbf rn dmhbljhhr fz dslql xcc ucc'f + pgtmyg zi apmtc fau apvv exobm < 0 slx aq vddq obvbbun izja ytmq rezhl < 0 + mev nmbycsgxy nmiqs 0 vmaxd mlzp kooogdu cmm zdbrg wm dgs tezko cm z + 3 jz + kiyd zutabvazp djbfm. Xllsw gph ua fmrhl zdi znxnm negr bepf dfl cmrq jndwvd + at xzqh pklr tykkh qgyueuohjk bju dlac orluw. Tp asplcstoi ec: + + /* ... */ + r<:z-3:> = (e < 1 ? 1 : (t > 5 ? 5 : l))-1; + +* Cqmsjzw nojcy ury lbmjhartv: + + cgyx n(keyq *t, xkh w, jek p) + { + mwb(k<:2:> = 0; i<:*E:>; ++y<:2:>) + { + y = p<:g<:2:>:>; + lx(e > 64 && w < 91) + b<:z<:2:>:> = (((f - 65 + b) % 26) + 65); + } + } + iexe S(wpsm) + { + niu(*n = 0; *h < 3; ++*d) + { + *F<:16+h<:1:>:>=W<:c<:j<:1:>-3:>:>; + U<:a<:1:>:>=V<:s<:-3+d<:1:>:>:>; + g(K[*q],*(m+q<:1:>-6)=r(N<:8:>,*F<:7:>),*w); + } + } + + + Cwpid wi lpj: tsj ep R osb n[2] ua 0 cmm dhznnawbz fs med nflc zefl wr odi + jpcz, mzv cvvh bru qeonzmjlw iyl wos nzbr jo r[*H]? + + Mvyjwh vwuyif cqp ntki zpmpxpxdkj si u[1] (ch m[1] mxt *b). Swea hfejidev (frspmdsx + bzkj k) ql tbkb py kot shmmwrqu zl ydxd uzjb cy cnvy ua k qfxo ne lckpojn + kgqobtub. Dlm gxo hk E eomo *a as zay lwdhchsy t()? Zn xhefhjo. Yyyfrptrid + dr zdv amis judtncyacf di nsfp Q owxt'g slrwx wlm enznshrvc 'p' no svt + ixlyxsul kgu oom k *i = i; kv ycv ijq us cgf gprgdtgv. Kyv wgos reitij Q sxb + dto vlfsexzf pwolxd ont iwugd J rgz hwi umti hs djvz asnaa ufryt c ccdsxou + odbu pkpcsbkeav at X bktkyaf nz bbbabr ikpf tsck vui qddfaa gin kui u + uoxljyswh yx k wpoazqsag ubvkfjml oiu bzx dzki thhcfby kvd mf mey rgtmbzn + jrbnqxlf wo nyp xnev be vuu H() ihrydudp (wio fzlnh bcb r rumegmm ne'l xfr + latpxgda). + + Eofkcmgdux U gxyi gzuymgw nypa kfon tdi pnc xn pjaqj np icfczqghhr dduyh + igjqdyxdpjr J ltcwsxa yi cd pyzf wr qc viv. Imvaoh: + + Saq ssi ojcq lco mznc D nwu atv qcozo hi t[1]-3 ez bkx ovpae qt A[q] (wx + P[w[j[1]-3]]) (T hfqoj B vflf irkz akwni; L vhaicfkj aew'n fbku hbr rfujbdy + matek qp otfl tqvyh kedon dzf jiwlwo hadua. Xdw rgcfkz cxva.v nt lwxinzc + exwx qjiaje xfbbgv.). + + +* Qi pil ezouvof rrzq reqim oen nanivbwk etlwird `o` hy tb khhz 13 elh A jbqvl +`f` ei oh `k + 10`. Ffx? Ytnhcwq: (1) Z pkbbowf gc nnqz kia nr zcz ln qgxl qz z +nzfrzvxpl hxbqgqmv ofuuzip ip s oampcyp xiq me hzd yqxdnvdt (dy gslf nc hiyvzk); +nwa (2) C wmwl'p nlgi is gmuu dyrgyaju lxh fcm jwcyuhh: sggl N yjdr evuh ztyu +wrknqmq `i[1]`. Vlrm P nazm fhhr: + + eza (*k = 0 ; *w < 10; ++*z) + { + m<:-2:> = X<:14:><:*(c+1):>; a<:-3:> = R<:15:><:1<:b:>:>; + xb (c<:-3:> && i<:-2:> == t<:-1:>) + ghzahk s<:-3:>; + en (z<:-2:> && w<:-3:> == c<:-1:>) + bbbpea o<:-2:>; + } + + Pfrp `h[1]` ep kuaigm lc pqq lbqa rl `*l` sf naces exj mq kbo mgr nds kev + uyudoxzv zejmscglgt (wwns lz qyn fpjvkdpob gp C ribr) nbn (tps ilmu bd vdxi + apenkb yipzq gym uled). Br gvx flwuo G'w hlyfqivlr cb mrw tuzckokm kv yfcq + hydz isj ken: *z hqy qxq xvljispuh uyc ughi q[1] unq ijr jyqrtb uqpnidx va + uxpv D[14] pdw Q[15]. O pcch yvkqfu bj ylx B (iwq z brzdn wmsujv zx R + 10) + sztiy H xhh jq uab crl rkzvv cq drxdtyd (rmpu wk mus cvjqymhtl yywjwfwl). + +* Iua tahlx gdfprofs P() jkpkj r `uoop z` vsq fax dya'i lmuboq ql uvgmi yxxu +gy xjz. Cjn? Cf umls K ddtu gs jgrc xr: + + v = U(d<:-1:>=n); + + Ywy xrmq yb fgxe jtiw yg e pcz zg kr csjk ia zxza qgo obxesdkf pmq jujynw ss + qvc cdafnh yfnvbhcm il ifv zvsh oprd: np mut rtanltll V B gdq's ekii miakm r + yiinblv ao'r xan fxkw xvegz vg q[-1] (ipfxr T ql hein zhhkh). Noh yj no + oegyxnbk sl X? Sbrqllg bu dkchjibrqsnj by vxuidak gfl nk fg xrcvn agvp qmvw + to evsh iahpj, wyz mtkd emq'i vrfu blv ga pmnfco s zgzrb bixn C Y kgcmc dwc + pldud zvvddemc gkdbwhd nt hxpab iicw qsbmvnylb. + +* Ytpjzhbl mbqj vq btumywn hdgatmr fsrxa to pon voyya yirby pwg pmrtf totm O +ygmlb er ydm xbpq mthybtwc yt peqk glyg cha snl (wh kb vkyu yjnzo kejan bzwk +irzqyqa xy bhk 'hkbj ajmbbrfb'). Am bkx W() javeeqtf cyk jhurcxb: + + z<:-2:> = I<:14:><:*(k+1):>; z<:-3:> = Q<:15:><:1<:z:>:>; + + D ngqov dm o[1] fw qcnn: *(y+1) jov 1[o]. + + +* Zawmighcc i gcgxhl fr `th .. `c xsrr `... && (...)`w (xv hfq pivh ke qdzwx +ll'l unvixk ypmmyjp: `e && (r = 0 && (u = X(D,g)));`). + +* Urhpp mrwbpapqf lanf ccejfh ew eux: bas zzphki rzehsdsq, axc hamxxuqgx gpa +wvb ymvibja xak xxkk bzjpi. Mrv ufcji bft fsu apsufcveoax: D sifl uyq 0ic +deznzqc dt ynpf uxkq my ytrl jxecc, bzkw ytf 1em ujqsnvh kqpd qf fjfi pjbhd svtt +quo 2sn cqfgwfz blmi cm rlen knbwt. Igsd dd'j zal kinho lalcqlnz. Unt klskd gob +ujgzuu bfdu nujozcx eldh pcphj ximovcnzrlid jtub `v+h%3` okk `o+o+1` tokyjjasd +dz qonqd 'jevoo' wf xoqiwx. Vr znkna xbntmg X fkzyt dt fcvmi lsduqkva uc yezooh +tsout (rtpf iu). + +* Glkwrjh otk lg todf jcncnr pb ldl: bxs dlqi irzvjq pp pokb iz qsh pig +hkxdjemrwv gg ydp `uygn [][27]`. Sbgq uywsk ojs eind kou tgvm fguo: + + (T<:x<:-10:>+5:><:a-'C':>) && (d = I<:c<:-10:>+5:><:y-'N':>); + + (Mx gbsupr oxsh exxv gvvkbgn no cl twbcdvurp tt yzhjwuz pjhf z &&). + +* Ff utup T pglukhm olus rgf fqrci kri xwsoeo em pwmlpo kyivav nm uj vrykdj +hxnk sph vjrh lh fwa geqz qyyyth wy sjjm'z lfbb W wwck ssji. Eeak mewo +ybhegsmxv unlewtfa rxv cwye'gv omjaklov ou uviaanlhzya. F owan nlxc dssj lvj +pkfxhpkul gzxebp ah obb piuq eentb (alu ove htuaealiktn cc unx plzajwa kcrgc). +Ppmegt svgh vmy vyqif T'n kbmvbpk nwatj zz sfp zojclts `D<:19:><:27:>`. + +* Mlb quubnwoe (uokg de mio xfcbpn). + +* Sxw qgksomobq (mduo nr wdw wloefz). + +* Oyx Ocyavb frkdynwx pyaw qtj xmivecccu yam ryslx (shno lcllihj). + +* Dgf jtefmrgz bamfcle (ookx aj chw puk cqbk eg hrr iqol gdnep hbdvkkl!) (qizu +ou dieub xwxey jed podb cd l pwothxzja smsbulv tp unn `tzbj S[19][27]` - nxi iqm +emu gxsuz). + +* W's bqi xrgx lhdd bv vyyzc nff qlc agbmjn esf rl grc hgq H xgip pqhm pejv; +ek lhjs ertflihgj eeift F kxsa figk wmg yapyx qbsgvwu px yxsby ky xqg cagndhc +qouc Y fwur xot bhps qpb dptmg brwvicc (xevky trwea m.y. `e[3][2]` oinif efqf +qjsxf hchf `*k[3]` un fqpojttn). Fqt om lto aetfia wqdid ggs 18 awazxbakm +xmjmvro (td pvga qomka llcg ekp xwmqr zltu sd izwnsukb) ss `eotk I[19][27]` vrzz +j bxqdgpofs fu ucazghgjn yqtv. Navd xj nrblm zji zq D auibk mqvwkgtaz. Lwvv +ajdvske xc nhqzr hxqxwh qqqbx vmkgy weqg cwxa lp'c rzlr xnlmi. + + +* Qmakxwts jyhwm J muyr lueu icg vo adu miqqfn gr qxq phs tm j zkw crrc jh pxd +xwxmbrooe uq won karm dqny lk dxff(): `y` pozq zia av vdqcq 0 wel Y honm rj sr 9 +vm O gv `x += 9` kw rqh oyqxnxzgafqeux wb vzl eza dbht ojyxvcy gm euxouw mqszpet +wm ba 9. + +* Lgi tdllym krz'z gbqn bjgqcvrrwqw zcgsasc nib R ztodpresyhug. Pzpc'b iztk +gmfaas nvzpqav xy qaqd kgrcfja nacsw sgn plje xwk qrvz mrj mba O thffzmuoebqg +qylgrz. Uja hpdieqvg Y ztdx fyhik j gnn nse rjuyiwhfgd Q iv kiq wlbhr ulvd tka +jhxtovcgfqp kye hkqomb au rxiq lnhme. Eps mqwdsujm: + + + %:nlblfu Y(n) vv(*k)=kauhfug(); gsayu((*e)=='\b') + + Ud bljs nlfpb r dajlmp tu dmcpy clv lvhixkug vm zbtqc nt c bvakhshy kcbn + bueor r gqcrfiz gs yi cjd mw yug tpxc hykufmpyfu nqrv myw (R dijppds wg ptgi + svdv rjylq lhl Q al bbpvcf isjk befw). Hezla spt zkeb bdcvhk ogf nnle sdr + mrxn rfxut (bx tc twxiu fnzp tv zyjn fd eu lik sgg). Jchtc gd gxd tl + zuchjlprdn Z vgqc pn vlroy zt uenrpp xinvkhk W orzkf bc'x h khkknwe bub pim + yw eyuo qx fe emtdpok yitvo tsndc: + + %:vibgut B(a) *(&F<:7:><:1:>+(w)) + + Drba fn xirqzee elsvw fmnt rcy: Ijfdj A ulpol tii L vzif rc ootgs rpotpahu + bm gwb hwivf vrvjuhko (J okkdu em utf hif jhvlj bmqmuvhj woecbs). Gna X + kknku echi hiao byr + + pwog d = F[7][1], p = T[7][3], s = T[7][5]; + + Thr T zdzc dttx owklc ukouxko jan nizqfsl nomzzwsort clo sjxro nfmiq. + Cajgemn dz dptc xfperqgklvqfe gjts htubt uncp hc s vytps: 17 fl O hnlzgu + npwro. Owze'g qkrx zyn guoiw. La R ehsw or zuzhcfh py xdwag axbqx qb yolwst + ev'c op uuhp fdmt. M lbclcuy adhpfo sbli dggk bbp osf ubmmpitwdc bc ug gghmc + wnjewliy dipt pyjcoju an xtnbqvtsb lkti z xz wgl pe R[7][1], y am N[7][3] + jag e pg I[7][5]. + + + +# Myedaiknkif azi cypyvk.u + +* Mt bxyhz nruzlmore J mrqd varx ooj gmei otvth il ywipksqdh wak avpfwkjqe +(ztsu uwejuq.p srg ystf sexlvhlgf zjg qxnozerkp) qfy ewbk prdnzyqus fpierwpi. +Wpg dlhbopi kx nsnxny.u `P` cw w `izkg Q[3]` ixp yp ctlo.u co'm `mebx *H[3]`. +Ioefrby srcyrtd ri bvcef bs ltal.m `S` oi `qfyi M[19][27]` ld odsgwu.w xg'f `bskz +*Z[3]`. Kufs ook byp ztlxv ibh vzy jhhfwuzlerc smj. R lkxltjl zkxr O ppal peua +nlg qqii dm s rpvngqak (xs jzbmg hrbro) ft xq hxn tffq sn l xqzvtvqu ei xkf +wckpd. Yjjw cl oad upyfyjvlh eflt pdg rokn qeghi frhxeyy ln qkbcj zlyntgx +oqjnregdc xbu gnlez qcg xbzwi zbof jtujx ngy wyudqukhb enuyt; xvs nueezi zp kvd +nvqx wh qoxo pensvqyl pguga nhcfm zp qeau izxlshec vsh ytxfnau syom osza nxk +ejhay frn ghzknu rvi smu hax io lzdy ciernobb att cbkc xrvlfwoqrrb fdm bnoxjp +iwggt xxp xp ojonynhe pzjbogv wry vbenwhvybt li ifvqw! Monwvnpvytxf ec udc +ypimayd cg unao gpbkzqoq V przxkswzhm kny uuzauyjt zd utdhaf.p (qqtwbr eco qvnik +qgmdgotv bpjk Y eqvv aunx zfzoawaft zduhn) lz'b oyd erltxld nzr Sqyuir +mzhbfh zgkhmcy H zzni'b jtlz affmgz.s fg vzbt udaz blfph eh ny ypb jnbv.p uahdb. +T tbr'd owrbrdr gfzoxuuyecz muzhxs.y yaec mtfzqyo zxi er jbhxl mbocr wokvjys +ebwgta.d neseh'u lcn hep Fcjrhb rndqkdkev meg oqmd cfk kwknylh vdp kfai mlzi +wcprsuhrehn (yrs ankxzlmxe) wy qxdn vju hbpzgj mzjfsx xkfmvsr eqx `xcfu` +xmppvaqwr cr mtmhyu.j, lijj yfcb ub qcvx.m, fvbbzok ctk fikufh ta xd dxbx pyovk. + +* Zzyz urdy mi wjzv myqnr ? + + /\ + / Unal eb *tsq* vtry xjb ipfwp: + itxb L(pgxc*n){ /* ... */ } + + + Gn djmn guhuh euj kk yi dru ttvm eg cqbqhdxl? Usj qq'k bqqxb lrv Q'ij nnycv + jcp qkpiz iylw pb cdt zvnjilax sw be sti vvpebo rz vakcln. Yrkc: qew iqftpit + mjdf fvs kn qecxd (fur, gcptvd xgk zj)! Hpnatjx mvyd: Sdqt kx nbe up ivv j + wxriuyfbof hkgckwy (tlotgwriqi edqb tccuf rixj fxhs zpfp dwvzquemdf - dqk + dyud iyr). diff --git a/ioccc/2020/ferguson2/prog.c b/ioccc/2020/ferguson2/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..69dd93bf02bd0e5fefdef1c9f6a6ae6de3462ff7 --- /dev/null +++ b/ioccc/2020/ferguson2/prog.c @@ -0,0 +1,59 @@ +%:include <stdio.h> +%:include <ctype.h> +%:include <string.h> +%:include <stdlib.h> +%:define J(x) do(*x)=getchar(); while((*x)=='\n') + +%:define A(y) *(&Y<:7:><:1:>+(y)) +%:define D strchr( +%:define q(s,x) D(s),(x))-(s) + +%:define n isalpha +%:define V(k) E = q(Y<:8:>,(k)) +%:define K fprintf(stderr, +%:define l(c) (c)=toupper((c)) +%:define W(a,b) (a)<:(q((a),(b)) + 1) % 26:> +%:define O(a) k = Y<:8:><:(E - (a) + 26)%26:> +%:define d(a,b) v=(a)<:(E+(b))%26:> +char*M,*R<:3:>,Y<:20:><:27:>=<% "EKMFLGDQVZNTOWYHXUSPAIBRCJ", +"AJDKSIRUXBLHWTMCQGZNPYFVOE" , "BDFHJLCPRTXVZNYEIWGAKMUSQO", +"ESOVPZJAYQUIRHXLNFTGKDCMWB" , "VZBRGITYUPSDNHLXAWMJQOFECK", +"YRUHQSLDPXNGOKMIEBFZCWVJAT" , "FVPJIAOYEDRZXWGCTKUQSBNMHL", +"ABBBCCQEVJZ","ABCDEFGHIJKLMNOPQRSTUVWXYZ", "Mjqq", "Lcxvago" +,"Huwfnbgt","Hdoqhmket fbvy","Mcromlhxo"} ,*S,*r; int *z=(int +<:13:>){ 0} ,*e,*g,*P; size_t L; char Z(char x){ for(*g=0; *g +<10;++*g) {r<:-2:>=Y<:14:><:*(e+1):>; r<:-3:>=Y<:15:><:1<:e:> +:>; if(r<:-3:> && r<:-2:> == r<:-1:>)return r<:-3:>; if (r<:- +2:>&&r<:-3:>==r<:-1:>)return r<:-2:>; }return x; } void w ( +char *s, int k, int v) { for(e<:2:> = 0; s<:*P:>; ++e<:2:>){ +v = s<:e<:2:>:>; if(v > 64 && v < 91) s<:e<:2:>:> = (((v - 65 ++k) % 26) + 65); } } void Q(void) { for(*g = 0; *g < 3; ++*g) +{ *Y<:16+e<:1:>:>=S<:e<:e<:1:>-3:>:>;R<:e<:1:>:>=Y<:e<:-3+e<: +1:>:>:>; w(R[*g],*(e+e<:1:>-6)=q(Y<:8:>,*Y<:7:>),*g); } }void +m(char*x){ char*p=x,a=A(0),b=A(2),c=A(4); int f,E; for( ; *p; +++p) { int u = islower(*p); if(n(l(*p))){char k=*p, v; f = 0; +c == *Y<:18:> && (f = 1) ; c=W(Y<:8:>,c); if (f) {f = 0; b == +*Y<:17:> && (f = 1); b = W(Y<:8:>,b); f &&(f = 0 && (a= W(Y<: +8:>,a))); }else if(b==*Y<:17:>){ b = W(Y<:8:>,b); a= W(Y<:8:> +,a); } k = Z(r<:-1:> =k); e<:-6:> = q (Y<:8:>,a); e<:-5:> = q +(Y<:8:>,b); e<:-4:>=q( Y<:8:>,c); V(k); d(R<:2:>,e<:-4:>); V( +v); O(e<:-4:>); V(k); d(R<:1:>,e<:-5:>); V(v); O(e<:-5:>); V( +k); d(*R,e<:-6:>); V(v) ; O(e<:-6:>);(Y<:e<:-10:>+ 5:><:k-'A' +:>)&&(k=Y<:e<:-10:>+5:><:k-'A':>); V(k); d(Y<:8:>,e<:-6:>); E +=q(*R,v); O(e<:-6:>); V(k); d(Y<:8:>,e<:-5:>); E= q (R<:1:>,v +); O(e<:-5:>); V(k); d(Y <:8:>,e<:-4:>); E = q(R<:2:>,v); O(e +<:-4:>); k = Z(r<:-1:>=k); *p = u? tolower(k):k; } } } void E +(char*x, int s, int i){ if (n(l(s))) x<:i:>=s; } int p(char x +) {return D 14<:Y:>,x)||D Y<:15:>,x); }int main(int i, char** +v) { int j; e = z + 10; S = Y<:7:> + 6; r = S + 10 ; g = e +1 +; P=g+1; for (j=-3; j < 0; ++j) e<:j:> = j+3; Q(); for (j +=9 +; j < 14; ++j) m(Y<:j:>); if (!(v<:1:> && *v<:1:>=='-')) goto +k; for (i = 0; i < 3; ++i) { K"%s %d: ",Y<:9:>, i+1); J(&j) ; +j = j - '0'; e<:i-3:>=(j <1 ? 1 : (j>5?5:j))-1; K"%s %d: ",Y +<:10:>,i+1); J(&j); E(Y<:7:>, j, i+i%3); K"%s %d: ",Y<:11:>,i ++1); J(&j); E(Y<:7:>, j,i+i+1); }K"%s: ",Y<:13:>); J(&j); e<: +-10:> = (j < 1 ? 1:(j>1?2:j))-1; for (i = 0; i<10; ++i) { int +a, b; K"%s %d: " , Y<:12:>,i+1); J(&a); J (&b);if (n(l(a))&& +n(l(b))&&a!=b&&!p(b)&&!p(a)) { Y<:14:><:i:> = a; 15<:Y:><:i:> += b; } %>k: Q(); if(getdelim(&M, &L, EOF, stdin) > 0) <%m(M); +printf("%s",M) ;} free (M) ;%> diff --git a/ioccc/2020/ferguson2/recode.1 b/ioccc/2020/ferguson2/recode.1 new file mode 100644 index 0000000000000000000000000000000000000000..e86dfeadc9e788e19e8e6cf2cedb33641010fd7e --- /dev/null +++ b/ioccc/2020/ferguson2/recode.1 @@ -0,0 +1,114 @@ +.TH recode 1 "30 April 2020" "recode" "IOCCC 2020" +.SH NAME +recode \- A configuration tool for the IOCCC 2020 Enigma simulator w/various additional features for enhanced usage +.SH SYNOPSIS +\fBrecode [options]\fP +.SH DESCRIPTION +\fBrecode\fP can randomise settings, save settings to a file (for future use of enciphering/deciphering), read an input file (to e.g. pass to the Enigma program) and it also can prompt the user for the settings, validating input, etc. +It allows for a much easier way to use the Enigma simulator and I recommend it for general use if you wish to change the settings of the Enigma simulator. +.SH OPTIONS +.PP +\fB\-h\fP +Show the options and exit. +.PP +\fB\-v\fP +Display the selected settings in detail. +.PP +\fB\-r\fP +Pseudo-randomly select the settings. +.PP +\fB\-f\<input file\>\fP +Read input file as data file (e.g. to pipe to Enigma program). +Notice that there is no space between the \fI\-f\fP and file name. +.PP +\fB\-i\<input file\>\fP +Alias for \fI\-f\fP option. +.PP +\fB\-R\<string|file\>\fP +Parse settings string (or file with the same format). This is far from perfect and there's no error detection (other than keeping the variables in the valid ranges where applicable)! +Notice that there is no space after the \fB\-R\fP. +.PP +\fB\-o\<output file\>\fP +Save the settings (not the data read in) to the output file for reuse. +.PP +.SH FILES +\fIrecode.c\fP +.RS +Source file to the recode program. +.RE +\fIrecode.markdown\fP +.RS +Markdown file with examples on how to use the recode program (along with the Enigma program). +.RE +\fIhint.text\fP +.RS +More information on the Enigma simulator IOCCC entry. +.RE +\fIchocolate\-cake.markdown\fP +.RS +A file with a recipe of a double-layered chocolate fudge cake that has been enciphered with one of 16 Enigma settings given in \fIrecode.markdown\fP which should give enough information on how to make use of the two programs in order to unlock this recipe (well worth it!). +.RE +\fIrecode.1\fP +.RS +I don't think you need help here! :) +.RE +.SH BUGS +.RS +\fB\-\fP The \fB\-R\fP option doesn't detect errors. +.RE +.RS +\fB\-\fP Doesn't handle input from other programs very well (e.g. \fBecho ...|./recode\fP). +Yes it's ironic that although the parser is better in some ways than the Enigma simulator itself it cannot handle being piped input whereas the simulator can (and vice versa)! +.RE +.RS +\fB\-\fP It was written by a human being. +.RE +.RS +\fB\-\fP The source code is ugly. This is only partly intentional. +.RE +.RS +\fB\-\fP A feature that some would like to call a bug, maybe: Deciphering how this program works won't help you figure out how the Enigma program works. +.RE +.RS +\fB\-\fP Options don't allow a space between the option char and the argument. +This in turn means that for options expecting a file name shell expansion won't occur which means using e.g. ~ will not correctly translate in the file name. +.RE +.SH EXAMPLES +.PP +Print out the actual Enigma settings of the config file in a human form: +.nf +.RS +\fB + echo | ./recode -Rconfig -v\fP +.fi +.RE +.PP +Does something special (what?): +.nf +.RS +\fB + echo | ./recode + echo | ./recode -v\fP +.fi +.RE +.PP +Please see the \fIrecode.markdown\fP and \fIhint.markdown\fP files for more examples and other information. +.SH AUTHOR +Written by Cody Boone Ferguson for IOCCC 2020 (the 27th IOCCC). +.SH SEE ALSO +.PP +\fBenigma(1)\fP +.PP +\fB\<https://ioccc.xexyl.net/2020/enigma\>\fP The 27th IOCCC 'Most enigmatic'. +.PP +\fB\<http://users.telenet.be/d.rijmenants/en/enigmaproc.htm\>\fP Enigma Message Procedures for the Heer (Army), Luftwaffe (Air Force) and Kriegsmarine (Navy). +.PP +\fB\<http://enigmaco.de/enigma/enigma.html\>\fP Online interactive Enigma simulator. +.PP +\fB\<http://www.codesandciphers.co.uk/enigma/index.htm\>\fP Tony Sale's (original curator of the Bletchley Park Museum) pages on The Enigma cipher machine. +.PP +\fB\<http://users.telenet.be/d.rijmenants/en/enigmatech.htm\>\fP Technical Details of the Enigma Machine. +.PP +\fB\<http://users.telenet.be/d.rijmenants/en/enigma.htm\>\fP The German Enigma Cipher Machine. +.PP +\fB\<http://www.ellsbury.com/enigma3.htm\>\fP How the Enigma was Set Up and Operated. diff --git a/ioccc/2020/ferguson2/recode.c b/ioccc/2020/ferguson2/recode.c new file mode 100644 index 0000000000000000000000000000000000000000..c7ef32a58ff1acc81c1da47162158c80a4471236 --- /dev/null +++ b/ioccc/2020/ferguson2/recode.c @@ -0,0 +1,67 @@ +%: include <string.h> +%: include <stdio.h> +%: include <ctype.h> +%: include <stdlib.h> +%: include <time.h> +%: include <unistd.h> +%: define W (char<: :> <: 4 :>){ " I"," II","III"," IV", " V"} +%:define E(x) do (*x) = getchar(); while ((*x)!='\n') +#define q Q"Invalid input. ") +#define Z(x) (x)=A<:F(0,25):> +%:define Q fprintf(stderr, + +%:define U (char<::>){"BC"} +#define L(V) (V)=toupper((V)) +%:define n isalpha + + /\ +/ This is *not* what you think: + + void D(char*x){ for(char*p=x; *p; ++p)*p=islower(*p) ?"nopqrstuvwxyzabcdefghijklm"<:(*p-97+26)%26:>:*p; } + char *M,*Y<:3:>,R<:3:>,A<::>="ABCDEFGHIJKLMNOPQRSTU" "VWXYZ",N<::><:27:> = { "EKMFLGDQVZNTOWYHXUSPAIBRCJ" + ,"AJDKSIRUXBLHWTMCQGZNPYFVOE","BDFHJLCPRTXVZNYEIWGA" "KMUSQO","ESOVPZJAYQUIRHXLNFTGKDCMWB","VZBRGITYUPSD" + "NHLXAWMJQOFECK"} ,o<::><:27:>={ "YRUHQSLDPXNGOKMIE" "BFZCWVJAT","FVPJIAOYEDRZXWGCTKUQSBNMHL"} ,P<::>="A" + "BC", T<::>="BBC",C<:2:><:11:>, g<:27:>,X<::><:21:>= { "Rbgbef", "Iachg ebgbe", "Iachg frggvat", "Iachg " + "cbfvgvba","Rrsyrpgbe", "Iachg ersyrpgbe","Iachg cy" "htobneq cnve","Rvat","frggvatf","cbfvgvba"} ; int K + <::>={ 0,1,2} ,y, H, v, c; size_t l; int F(int i,int j) { return(rand()%(j-i+1))+i; } void d(void){ int i + ,j,k; srand((unsigned)time(0)); strcpy(g,A); K<:0:>= F(0,4); while((K<:1:>=F(0,4))==K<:0:>) ; while((K<:2 + :>=F(0,4))==K<:0:>||K<:2:>==K<:1:>) ; y=F(0,1); for( i=0; i<3; ++i){ Z(P<:i:>); Z(T<:i:>); } k=0; while ( + k<10){ do i=F(0,25); while (g<:i:> == ' '); do j=F(0 ,25); while(j==i||g<:j:>==' '); C<:0:><:k:>=g<: i:>; + C<: 1 :> <: k ++:> = g<: j:>; g<:i:>=' '; g<:j:>=' ' ; } H=1; } int p(char x){ return strchr(C<:0:>,x) || + + strchr(C<:1:>,x); } char B<:3:>; void G(void){ * B ='\0'; scanf("%2s", B); } void m(void) { int i, j=0,h; + char k; Q"%s:\n",*X); for(i=0; i<5; ++i)Q"(%d) %s: ""%s\n", i+1,W<:i:>,N<:i:>); for(i=0; i< 3; ) { x : Q + "%s %d (1 - 5): ", X <:1:>,i+1); G(); j=strtol(B,0,0); if (j<1||j>5) { q; E(&j); continue + ; } j =(j < 1 ?1:(j> 5?5:j))-1; h=i-1; for(; h>= 0; --h) { if(K<:h:>== j){ Q"Already use" + "d. "); E(&j); goto x; } } K<:i++:>=j; E(& j); } for(i=0; i<3; ++i) { i:Q"%s %d (A - Z)" + ": ", 2<:X:>,i+1); G(); if(!n(k=*B)){ q; E(&*B); goto i; } P<:i:> = toupper(k); E(&*B); } for (i = 0; i<3 + ; ++i){ j:Q"%s %d (A - Z): ",X<:3:>,i+1); G(); if(!n(k=*B)){ q; E(&*B); goto j; } T<:i:>= toupper(k); E(& + *B); } Q"%s:\n",X <: 4 :>); for(i = 0; i < 2 ; ++i)Q"(%d) (%c) %s\n", i + 1, U<:i:>, o<:i:> ) ; k:y =0; Q + "%s (1 - 2): ", 5<:X:>); G(); y=strtol(B,0,0); if (y < 1 || y > 2) { q; E( & y); goto k ; } y=(y<1?1:(y > + 1 ?2:y))-1; strcpy(g,A); for (i=0; i<10; ++i) { char a,b; v:a = b = '.'; Q"%s %d: ",6<:X:>,i+1); G(); a=B + <:0:>; b=B<:1:>; L(a); L(b); if((n(a)&&!n(b))||(!n(a)&&n(b))||(n(a) && (a== b || (p(a)||p(b)))))<%if((p(a + )||(b))&&(n(a)&&n(b))) Q"Already used. "); else q; E(&a); goto v; } a=n(a)?a:'.'; b=n(b)?b:'.'; C<:0:><:i + :>=a; C<:1:><:i:>=b; if(n(a)){g<:a-'A':>=' ';g<:b-'A':>=' '; }E(&a); } }void e(void) { int i; for(i=0;i<3 + ; ++i)Q"%s %d: (%s) %s\n", 7 <:X:>,i+1,W<:K<:i:>:>,N<:K<:i:>:>); Q"%s %s: %s\n",7<:X:>,X<:8:>, P); Q"%s" + " %ss"": %s\n", X<:7:>,*(X+9),T) ; Q "%s: (%c) %s\n",4<:X:>,U<:y:>,o<:y:>) ; for(i=0,L(6<:X:><:6:>); i<10 + ; ++i)Q"%c%s #%02d: %c%c\n", X<:6:><:6:>,7+6<:X:>, i+1, C<:0:><:i:>, C<:1:><:i:>); } int O(const char*p){ + int i,j=0; char*x=0; FILE *f = fopen(p, "r"); if(f){ if(getdelim(&x,&l,EOF,f)>0){ p = x; j = 1; } fclose( + f); } l = 0; if(strlen(p) > 29) { for(i = 0; i < 3; ++i){ K<:i:>=(*p++)-'0'; K<:i:> = (K<:i:> < 1 ? 1 : ( + K<:i:>> 5 ? 5 : K<:i :>))-1; P<:i:> = *p++; T<:i:> = *p++ ; } y = ( * p ++)-'0'; y=(y<1?1: + (y>1?2:y))-1; for(i= 0; i<10; ++i){ C<:0:><:i:>=*p++; C<:1:><:i:>=*p++; } if (j) free(x) ; + return 1 ; } if (j) free(x); return 0; } void x(FILE*f,int k) { int i; for (i=0; i <3; ++ + i){ fprintf(f,"%d",K<:i:>+1); fprintf(f,"%c",P<:i :>);fprintf(f,"%c", T<:i:>); } fprintf(f, "%d", y + 1); + for (i= 0; i<10; ++i)fprintf(f,"%c%c",C<:0:><:i:>,C <:1:><:i:>); if(f==stdout&&k)fprintf(f,"%s",M); } int + + t(const char*a,const char *b) { int i, j; for (i = 0 ; *(a+i) || *(b+ i); ++i) if ((j = tolower(a<:i:>) - + tolower(b<:i:>))){ if (j < 0) return -1; return 1; } return 0; } int main(int V, char **I){ FILE*w=stdin, + *z=NULL; const char*p, *J="", *k= ""; int i; ssize_t s; for(i = 0; i < 10; ++i) D(i<:X:>); for(V = 1; I<: + V:>; ++V) { if (*(p = I<: V :>) =='-') { switch (*++ p){ case'h':Q"usage: %s [options]\n-v\t\t\tdisplay " + "selected settings\n-r\t\t\tpseudo-randomly select " "settings\n-f<input file>\t\tread file for Enigma i" + "nput\n-R<string|file>\t\tinit settings from settin" "gs string or file\n-o<output file>\t\twrite settin" + "gs to file\n", * I); return 0; case 'v':c=1; break; case'r':if(!H){ v=1; d(); } break; case'R':H= O(++p) + ; break; case'f':J=++ p; break; case'o':k=++p; break ; default:break; } } } if(*J){ w = fopen(J, "r"); if + (! w) { Q"couldn't open input file, using stdin\n"); w=stdin; } } if (*J && *k && !t(J,k)){ Q"same input" + "/output filenames, won't open for writing\n") ; k = ""; } if (*k) { z=fopen(k, "w"); if (!z) Q"couldn't" + " open output file, only using stdout\n"); } if (!v && !H && isatty(0)) m(); if (c) e(); s = getdelim(&M + ,&l,EOF,w); if(w!=stdin)fclose(w); if (z){ x(z,s>0); fclose(z); } x(stdout,s>0); free(M); return 0; } diff --git a/ioccc/2020/ferguson2/recode.text b/ioccc/2020/ferguson2/recode.text new file mode 100644 index 0000000000000000000000000000000000000000..7596de082c195a964eb88f6f86889c74555772a3 --- /dev/null +++ b/ioccc/2020/ferguson2/recode.text @@ -0,0 +1,572 @@ +# The recode configurator documentation (and a fun way to explore my 2020 IOCCC Enigma simulator) + +N.B. At the end of this file I have given a fun exercise that can be used to +explore my Enigma simulator. It's especially worth doing if you you like +good chocolate and could use a delicious [Double-layered Chocolate Fudge Cake][]. + +Alternatively if you just want the recipe you could look at my Snake entry +'Don't tread on me award' since it's also there and not enciphered. + +<a name="toc"></a> +- [What is recode and why is it recommended?](#recode) +- [Options](#options) + * [Protecting against the same I/O file](#samefile) + * [File options parser limitation](#fileoptions) + * [-R option validation?](#validation) +- [Piping commands to recode](#pipingtorecode) +- [Piping recode to the Enigma simulator](#pipingtoenigma) +- [Manually test the recode program with the Enigma program](#manuallytest) +- [Only write config file](#onlyconfig) +- [Reusing a configuration](#reuseconfig) +- [Write config file, read data file and pass to Enigma simulator](#passtoenigma) +- [Piping directly to the Enigma code once (with randomised settings, saved)](#directlytoenigma) +- [Usage conclusion](#conclusion) +- [Example additions](#additions) +- [Example uses](#exampleuses) +- [Delicious Enigma: Double-layered Chocolate Fudge Cake](#cake) + +# <a name="recode" href="#toc">What is recode and why is it recommended?</a> + +To demonstrate how to and why you should use the recode program with the Enigma +simulator I have included some examples here as well as brief ('brief?!' I am sure +many would think but it's brief for me) commentary. + +It would not be possible to do all that the recode program does in my entry +itself but I wanted to demonstrate the features of my entry and this seemed the +best way to do that. It also enhances the use of the simulator to make it +reusable etc. + +The recode name idea is that it recodes the input (validating first) to be input +for the simulator itself. It can pseudo-randomly select all the settings, it can +write the settings to a file, read from input file (e.g. for the text to +encipher if piped to the simulator) etc. + +Basically it's a configurator for the Enigma simulator that makes it easier to +use the simulator as well as to reuse the configuration to decipher messages +that have been enciphered by those settings. But it also tries to make it look +more like the real thing in that it shows the actual rotors (labelling them with +the Roman numeral), the reflectors (labelling them with B, C and showing the +actual strings) etc. + +In this file I will show an example of each feature and then get to the +wonderful 'challenge' for everyone. + +# <a name="options" href="#toc">Options</a> + + usage: ./recode [options] + -v display selected settings + -r pseudo-randomly select settings + -f<input file> read file for Enigma input + -R<string|file> init settings from settings string or file + -o<output file> write settings to file + + + +`-r` randomises settings. It won't prompt you for settings but it will for input +if you don't give the option to read in a file for input. + +`-v` shows selected settings. For example combining `-r` and `-v`: + + $ echo IOCCC | ./recode -r -v + Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ + Ring 2: ( V) VZBRGITYUPSDNHLXAWMJQOFECK + Ring 3: ( IV) ESOVPZJAYQUIRHXLNFTGKDCMWB + Ring settings: WAR + Ring positions: XKE + Reflector: (B) YRUHQSLDPXNGOKMIEBFZCWVJAT + Plugboard pair #01: XE + Plugboard pair #02: HJ + Plugboard pair #03: SA + Plugboard pair #04: PY + Plugboard pair #05: CI + Plugboard pair #06: ZB + Plugboard pair #07: WD + Plugboard pair #08: QN + Plugboard pair #09: RU + Plugboard pair #10: VG + 1WX5AK4RE1XEHJSAPYCIZBWDQNRUVGIOCCC + +Though you won't find such strings in recode.c or prog.c. (You will find the +Roman numerals for the rotors and the 'A' and 'B' for the reflectors in recode.c +though). Yes the 'WAR' for the Ringstellung (Ring settings) is an amusing +coincidence *but it really did happen!* + +As for `-f` the contents would be output with the settings e.g. to pipe to +prog itself (as if you redirected the file contents to prog for decipherment). +If the file cannot be opened it sets back to stdin. + +`-o` outputs the settings to the file. If the file cannot be opened for writing +or is the same file name (see below) then only stdout will be used. Example of +randomised output going to a file: + + $ ./recode -r -oconfig + IOCCC + 3PP4UB5GG1ELGTKFCOPVBNUYXJAWSDIOCCC + $ cat config + 3PP4UB5GG1ELGTKFCOPVBNUYXJAWSD$ + +Notice that a terminating newline isn't added. Also note that it outputs to +stdout so you can pipe it to prog but at the same time have the settings +saved for deciphering the text later (the configuration does not have the input +but both the configuration and the input text is printed to stdout). + +If you want to initialise the settings from previously saved settings (as a +string or an input file that has the same format) use the `-R<settings>` option. +Again note that this does not validate input! Although it detects out of range +for the arrays it doesn't detect duplicates. This is because it wasn't meant to +be any given file nor anything but the direct output of a previous run (thus +validated). I'm not even guaranteeing that I got the array tests valid in +recode.c -R option! + + +## <a name="samefile" href="#toc">Protecting against the same I/O file</a> + +Because some file systems are case-insensitive I have implemented a +case-insensitive strcmp(); if the input file name is the same as the output file +name I won't write to it. From a quick test this is important particularly if +neither file exist because if both calls to stat() fail then the inodes will be +the same (since what else could they be set to but the same initial value?). +This might be overprotective but I believe it better to prevent user error where +possible. Of course if neither file exists it might be argued that it's not +necessary to worry since you can't read from a file that doesn't exist. But then +what about if one exists but the other does not? + +## <a name="fileoptions" href="#toc">File options parser limitation</a> + +Due to the way the parsing of options is done (no spaces between option char and +argument) shell expansion will not work right so for example doing: + + $ ./recode -R~/config + +Will not read the file 'config' in the home directory. I show another way to +achieve this later. + +This limitation also applies to the `-f` and `-o` options! + + +## <a name="validation" href="#toc">-R option validation?</a> + +Again the `-R` option does not validate input. For validation you have to run +the program interactively. + +# <a name="pipingtorecode" href="#toc">Piping commands to recode</a> + +If stdin is not a tty (`!isatty(0)`) and neither randomised mode nor reading in +from a file is specified then you might just see something like: + + $ echo testing test tests | ./recode + 1AB2BB3CC1testing test tests + + $ echo testing test tests | ./recode | ./prog - 2>/dev/null + mfrwxan lzng ofnlu + + $ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode + 1AB2BB3CC1mfrwxan lzng ofnlu + + $ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode | ./prog - 2>/dev/null + testing test tests + + +In other words just the defaults. This was to simplify the problems with +prompting again for input if it's invalid (though as you'll see it does a good +job at this anyway). + + +# <a name="pipingtoenigma" href="#toc">Piping recode to the Enigma simulator</a> + +If you're using recode to recode the input so you don't have to type in the +input manually (if you randomise or read in from previously saved file no input +need be done at all) then make sure to redirect stderr to /dev/null. If you +don't you might see something like: + + $ ./recode -r | ./prog - + Ring 1: IOCCC + Setting 1: Position 1: Ring 2: Setting 2: Position 2: Ring 3: Setting 3: Position 3: Reflector: Plugboard pair 1: Plugboard pair 2: Plugboard pair 3: Plugboard pair 4: Plugboard pair 5: Plugboard pair 6: Plugboard pair 7: Plugboard pair 8: Plugboard pair 9: Plugboard pair 10: DEVIY + +What happened is that `Ring 1: ` is printed to stderr but since it's not been +redirected to /dev/null it prints this out; at this point however it prompts for +input. Why or how it shows the first prompt instead of later on I do not know. +Anyway at this point the simulator is already expecting input to en/decipher. +That's why after I sent EOF it printed out the remaining strings to stderr. + + + +# <a name="manuallytest" href="#toc">Manually test the recode program with the Enigma program</a> + + $ cat input + IOCCC + + $ ./recode -finput + Rotors: + (1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ + (2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE + (3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO + (4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB + (5) V: VZBRGITYUPSDNHLXAWMJQOFECK + Input rotor 1 (1 - 5): 1 + Input rotor 2 (1 - 5): 2 + Input rotor 3 (1 - 5): 3 + Input setting 1 (A - Z): A + Input setting 2 (A - Z): A + Input setting 3 (A - Z): A + Input position 1 (A - Z): A + Input position 2 (A - Z): A + Input position 3 (A - Z): A + Reflector: + (1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT + (2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL + Input reflector (1 - 2): 2 + Input plugboard pair 1: AB + Input plugboard pair 2: CD + Input plugboard pair 3: .. + Input plugboard pair 4: EF + Input plugboard pair 5: GH + Input plugboard pair 6: IJ + Input plugboard pair 7: KL + Input plugboard pair 8: MN + Input plugboard pair 9: OP + Input plugboard pair 10: QR + 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC + +Notice that I skipped a plugboard pair; this can be done in a number of ways but +two dots is one. Notice also that it's in a different order than the simulator: +because with the size restrictions on my entry I saved bytes by using the same +loop where I could. It just felt more natural to have them grouped together in a +configurator for the simulator. + + $ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null + HQNVO + $ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null | echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRHQNVO | ./prog - 2>/dev/null + IOCCC + + +As you can see the recode program prompts for the settings and outputs the +input for the Enigma program. I then copied/pasted that output to the program +and got the result HQNVO. + +Following this I piped the original output (of recode) to the simulator and then +piped that to the echo of the input settings (replacing the IOCCC with the +Enigma enciphered output) and then got the result IOCCC: the original input! +(This was before I implemented the `-R` option to greatly simplify things.) + +Of course the last command was redundant in that I didn't need to show the first +part again; I could have just done the latter part but I wanted to show the way +the pipeline works with settings etc. + +What happens if the plugboard pairs are the same but in a different order? It's +the same output: + + $ echo 1AA2AA3AA2AB..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null + HQNVO + +Also if you flip the order of the letters in the pair e.g. the AB as BA instead: + + $ echo 1AA2AA3AA2BA..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null + HQNVO + + +# <a name="onlyconfig" href="#toc">Only write config file</a> + + $ ./recode -v -oconfig -finput >/dev/null + Rotors: + (1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ + (2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE + (3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO + (4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB + (5) V: VZBRGITYUPSDNHLXAWMJQOFECK + Input rotor 1 (1 - 5): 1 + Input rotor 2 (1 - 5): 2 + Input rotor 3 (1 - 5): 3 + Input setting 1 (A - Z): A + Input setting 2 (A - Z): C + Input setting 3 (A - Z): E + Input position 1 (A - Z): B + Input position 2 (A - Z): D + Input position 3 (A - Z): F + Reflector: + (1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT + (2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL + Input reflector (1 - 2): 2 + Input plugboard pair 1: AB + Input plugboard pair 2: CD + Input plugboard pair 3: EF + Input plugboard pair 4: GHIJ + Input plugboard pair 5: IJ + Input plugboard pair 6: KL + Input plugboard pair 7: MN + Input plugboard pair 8: OP + Input plugboard pair 9: QR + Input plugboard pair 10: ST + Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ + Ring 2: ( II) AJDKSIRUXBLHWTMCQGZNPYFVOE + Ring 3: (III) BDFHJLCPRTXVZNYEIWGAKMUSQO + Ring settings: ACE + Ring positions: BDF + Reflector: (C) FVPJIAOYEDRZXWGCTKUQSBNMHL + Plugboard pair #01: AB + Plugboard pair #02: CD + Plugboard pair #03: EF + Plugboard pair #04: GH + Plugboard pair #05: IJ + Plugboard pair #06: KL + Plugboard pair #07: MN + Plugboard pair #08: OP + Plugboard pair #09: QR + Plugboard pair #10: ST + +Notice that I redirect stdout to /dev/null so that the config is only written to +the file config. But also notice that for plugboard pair 4 I typed in `GHIJ` and +it didn't report an error. Neither did it complain about `IJ` in the next pair. +This is because it consumes input overflow. + +It shouldn't be this way for the simulator though because that could cause +inconsistent number of characters expected before the text to encipher. + + + $ cat config + 1AB2CD3EF2ABCDEFGHIJKLMNOPQRST + + $ ( cat config ; cat input ) | ./prog - 2>/dev/null + LRAVE + + $ ( cat config ; cat input ) | ./prog - 2>/dev/null | ( cat config ; echo LRAVE ) | ./prog - 2>/dev/null + IOCCC + + +What if you don't want to worry about having to specify input but just have the +settings written? You can do that too by either sending a newline or else +directly type ctrl-d (or whatever you have EOF set to) or give it an empty file. + +The following are all equivalent in that they will write to a settings file (the +first one will print a newline with the echo but that won't matter): + + $ echo | ./recode -r -osettings + $ echo -n | ./recode -r -osettings + $ > empty + $ ./recode -r -osettings < empty + $ cat empty | ./recode -r -osettings + $ ./recode -r -osettings + ^D + +(Above ^D was not shown but I typed it.) The way it works: if nothing is read +the buffer remains NULL and so I don't print it but still do print the settings +file. Actually even if getdelim() fails you're supposed to free the buffer so I +set another variable to indicate if it should be printed. + +# <a name="reuseconfig" href="#toc">Reusing a configuration</a> + + $ echo -n|./recode -r -oconfig + 4UH5II1RJ1SPIFEJLYGZWRTBHVCAMN$ + + $ cat input.txt + IOCCC 2020 Enigma simulator example text file + + This is a sentence. + + This is another sentence. + + $ ( cat config ; cat input.txt ) | ./prog - 2>/dev/null > output + $ cat output + AAPRT 2020 Dkemny tpgnjsjai xpovrgl jvgs wxra + + Fytt ly m xyiilaqh. + + Ybbp ox dmuzerm oscwgytb. + $ ( cat config ; cat output ) | ./prog - 2>/dev/null > io + $ diff io input.txt + $ + +Alternatively you can just use the `-R` and `-f` options: + + $ ./recode -finput.txt -Rconfig | ./prog - 2>/dev/null > output2 + $ diff output output2 + $ + + +# <a name="passtoenigma" href="#toc">Write config file, read data file and pass to Enigma simulator</a> + + $ ./recode -finput.txt -oconfig | ./prog - 2>/dev/null > output + Rotors: + (1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ + (2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE + (3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO + (4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB + (5) V: VZBRGITYUPSDNHLXAWMJQOFECK + Input rotor 1 (1 - 5): 2 + Input rotor 2 (1 - 5): 5 + Input rotor 3 (1 - 5): 3 + Input setting 1 (A - Z): C + Input setting 2 (A - Z): O + Input setting 3 (A - Z): D + Input position 1 (A - Z): E + Input position 2 (A - Z): L + Input position 3 (A - Z): O + Reflector: + (1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT + (2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL + Input reflector (1 - 2): 2 + Input plugboard pair 1: TR + Input plugboard pair 2: SN + Input plugboard pair 3: OG + Input plugboard pair 4: ME + Input plugboard pair 5: XY + Input plugboard pair 6: WZ + Input plugboard pair 7: UV + Input plugboard pair 8: AB + Input plugboard pair 9: CD + Input plugboard pair 10: FI + + $ cat config + 2CE5OL3DO2TRSNOGMEXYWZUVABCDFI + +Besides a famous book that I happen to love (who doesn't? Ah, but what is it +Cody?) there's also a reference to code which I also love (just as all +participants of the IOCCC do). But what matters is the output: + + $ cat output + DBFAF 2020 Ittejg ltblwriac uqdfqvr dhqh ghhf + + Jsjy ce v pxdmullo. + + Sara tj rtaayak uxfhjcti. + + $ ./recode -Rconfig -foutput | ./prog - 2>/dev/null + IOCCC 2020 Enigma simulator example text file + + This is a sentence. + + This is another sentence. + + + +# <a name="directlytoenigma" href="#toc">Piping directly to the Enigma code once (with randomised settings, saved)</a> + +This is like the above only randomised: + + $ ./recode -r -oconfig|./prog - 2>/dev/null + IOCCC + UGEVP + + +Note that I typed in IOCCC and sent EOF (ctrl-d); the settings were written to +the config file (for deciphering later) and then all of it was piped to the +Enigma entry resulting in the line below IOCCC. But let's verify it worked out +okay: + + $ cat config + 2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ + +Without having to copy/paste intermediate results: + + $ echo IOCCC | ./recode -Rconfig | ./prog - 2>/dev/null | ./recode -Rconfig | ./prog - 2>/dev/null + IOCCC + +You can also use a string for the `-R` option. I'll use command substitution and +actual pasting to demonstrate: + + $ echo IOCCC | ./recode -R$(cat config) | ./prog - 2>/dev/null | ./recode -R2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ | ./prog - 2>/dev/null + IOCCC + + +# <a name="conclusion" href="#toc">Usage conclusion</a> + +That should give you an idea of how to use the recode program. I leave it as +an exercise to the reader to implement additional features but here are some +ideas of what could be done and how this entry might be used (including that +delicious challenge). + +# <a name="additions" href="#toc">Example additions</a> + +* Add code (to prog.c) that tries to determine possible decipherments based on +a given crib (or set of cribs). + +# <a name="exampleuses" href="#toc">Example uses</a> + +* Take an actual key sheet and message for that day and try and decipher the +message (might help if you know German!). I haven't actually done this for +reasons I explained in the remarks (including that I cannot easily verify one +particular as well as the fact that there were different procedures, different +machines etc. - plus my vision is not good enough for the quality of the +pictures). + +* Try making sense of a politician's speeches by putting them into the +simulator. It might not make much sense but can it honestly be that much worse ? +:) Actually yes it could be (and we don't need the Enigma helping them either) +and I can think of a whole host of other things more entertaining including +watching dry paint stay dry on a wall but why not poke fun at politicians +anyway? + +* Best idea: try the below experiment! + +# <a name="cake" href="#toc">Delicious Enigma: Double-layered Chocolate Fudge Cake</a> + +As I was making the above silly list something occurred to me. My other entries +this year include a recipe for a wonderful double-layered chocolate fudge cake +but why would it not be included in this one too? But then if that's the case +why on Earth should it be unscrambled? + +So this is what I offer: if you take one of the settings below and run the +simulator on the file [chocolate-cake.html][] you will have a wonderful +chocolate cake recipe (that even my late stepmum who didn't even like chocolate +loved - it's a speciality of my mum's and they were the best of friends too). If +you're lazy just go and look at my other entry. Then again if you're lazy you're +probably not reading this far! :) + +The settings is one of the below but a couple questions you might ask yourself: + +1. Are any invalid input? + +2. Is there some other kind of trickery involved here? + +I can think of the best way to answer these and I think I need not even mention +it. Have fun and enjoy! BTW: Depending on where you are in this world and how +warm it is the icing can be a bit of an issue - I give some ideas in the file on +what can be done for this. At worst though the icing won't come out as good as +it usually does. + + +Hints: + +1. It's not the middle one. + +2. Yes there are some things kind of spelt here. These include things about +cake and chocolate. Some things spelt mean nothing whatever and can be +considered coincidences. Some were randomised. + +3. There is an obscure thing about my entry that can help locate the proper key +of the 16 given below! The questions are what is it and is is it worth going +this way? (I think the second answer is 'no' but that's me.) + +4. The above points might or might not be relevant. What is relevant is one +will reveal a wonderful [Double-layered Chocolate Fudge Cake][] recipe: + + 142CHOCOLATESVCAKESTBJLKMUMVWX + 0EZ4PC1CC0PGTAQSOXWNMDRYKFUZEI + 3UY0XF4QG1GTJQLARPKHBEMCOFVUIN + 0WE1HK4PL0RVSGXFDKENZYTPCMAHUW + 2LV0KC1IE0HTFPCLWOJDBQIRVMEAGN + 1SS4QX2RY1SRAQGKUYHCBLPFJDVTNZ + 3IW1QR0TZ0GQEDWIYJUPMFZBRAONHS + 3OP1KN4MO0HPFZCEAKYQIRXGVMOTUW + 4OC2CC0AK1CODELUVRSNGKIZBJPTMY + 4MU0MS1CA1KELUVRSXTABJNOCDMQFG + 0MU4MC2HO1CLATEFBJMONPQRVWXYZD + 125CHOCOLATESEXCAKESJADFNOPQRS + 0CH3OC1OL1ATEMBJNOCDLSIFWHRVXY + 4MU1MS3CA0KECHOLATBJSNPXVUFGZY + 4VW0SL1YB0IYJSLBECKTNAXGPUVHRF + 0MC4OH2CO1LATEUMBJCDFGHINOPRQS + + +BTW: What's the middle of a list with even numbered items anyway? + +[chocolate-cake.html]: chocolate-cake.html +[Double-layered Chocolate Fudge Cake]: chocolate-cake.html + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/ferguson2/try.this.txt b/ioccc/2020/ferguson2/try.this.txt new file mode 100644 index 0000000000000000000000000000000000000000..5a5b42e0d80278c33ff3b216bc621416a398c063 --- /dev/null +++ b/ioccc/2020/ferguson2/try.this.txt @@ -0,0 +1,21 @@ +3 +I +O +1 +C +C +5 +C +Z +2 +CO +DE +SN +XY +MS +AT +VF +UR +KL +BJ +IOCCC diff --git a/ioccc/2020/giles/Makefile b/ioccc/2020/giles/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e4c8e5e522efd84bab101f8650b046c30cc056c8 --- /dev/null +++ b/ioccc/2020/giles/Makefile @@ -0,0 +1,590 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-disabled-macro-expansion -Wno-empty-body -Wno-float-conversion -Wno-float-equal \ + -Wno-missing-variable-declarations -Wno-shadow -Wno-shorten-64-to-32 -Wno-sign-conversion \ + -Wno-string-plus-char -Wno-string-plus-int -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-empty-body -Wno-string-plus-char -Wno-string-plus-int -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-empty-body -Wno-string-plus-char -Wno-string-plus-int -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +#CSTD= -std=c11 +CSTD= -std=c99 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o +DATA= dtmf.bin pi.wav +TARGET= prog +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/giles/compile_commands.json b/ioccc/2020/giles/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..2f7c4cc625ef6ee593018af2fbe4140f0694aeb7 --- /dev/null +++ b/ioccc/2020/giles/compile_commands.json @@ -0,0 +1,22 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c99", + "-Wall", + "-Wextra", + "-pedantic", + "-Wno-empty-body", + "-Wno-string-plus-char", + "-Wno-string-plus-int", + "-Wno-unknown-warning-option", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/giles/dtmf.bin b/ioccc/2020/giles/dtmf.bin new file mode 100644 index 0000000000000000000000000000000000000000..cba357828c0468bef421969c071eba3d00bd879d Binary files /dev/null and b/ioccc/2020/giles/dtmf.bin differ diff --git a/ioccc/2020/giles/hint.text b/ioccc/2020/giles/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..18480ef230250a423d072ba3b7a8c0b94b3f94e4 --- /dev/null +++ b/ioccc/2020/giles/hint.text @@ -0,0 +1,97 @@ +# Most phony + +Edward Giles +<https://id523a.com/> + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog + +### Try: + + ./prog < pi.wav + + # [https://en.wikipedia.org/wiki/867-5309/Jenny] + ./prog 867-5309 > jenny.wav + + # Use an audio player to play jenny.wav + +### Selected Judges Remarks: + +A cross platform utility for both encoding and decoding tones. + +## Author's comments: +### Introduction and Usage + +This program encodes and decodes [dual-tone multiple frequency](https://en.wikipedia.org/wiki/Dual-tone_multi-frequency_signaling) signals used in telephone systems, more commonly known as Touch-Tones. + +If the program is executed with no arguments, it will read a WAV file from standard input, decode the touch-tones in the file, and output the corresponding digits to standard output. This program only supports WAV files that have exactly 16 bits per sample, but it allows any sample rate and any number of audio channels. + + $ ./prog < pi.wav + 31415926 + +If the program is executed with a command-line argument, it will generate the tones corresponding to the specified characters, writing them to standard output as a WAV file. + + $ ./prog 867-5309 | aplay + +### Interesting Features + +* When compiled with `gcc -pedantic -Wall -Wextra` there are no compiler warnings. +* This program can be successfully compiled and run on Windows, using both Microsoft's C compiler and [TCC](https://bellard.org/tcc/). +* This program resamples the incoming audio, so that it can accept audio data at any sample rate. +* The code that generates the output sine-waves is the same as the code that looks for sine-waves in the input. (see Algorithm Details for roughly how this works) +* Despite handling lots of sine waves, the program only uses basic arithmetic operations. It does not depend on `libm`. +* All type punning is done with `memcpy` so there are no strict-aliasing violations. +* The size of the source code using the IOCCC size tool is 1963, the year the first push-button telephones were made available to customers. +* The source code is roughly in the shape of a telephone handset. + +### Assumptions + +* Code is compiled using the C99 or C11 standard +* `CHAR_BIT == 8` +* Machine is little-endian +* `int16_t`, `uint16_t`, and `uint32_t` exist +* `int16_t` is 2's-complement +* `double` is an IEEE 754 binary64 floating-point type +* `sizeof(double) == 8` + +### Obfuscations + + * DSP code is inherently somewhat difficult to understand. + * Lots of identifier reuse. Each identifier is used for about 2.2 different tasks, on average. + For example, `aa` is both a variable and a macro for error handling, + and `memcpy` is both a library function and a goto-label. + * Most of the identifiers are only 1 or 2 characters long, and are unrelated to their actual function. + * The `f` macro is used to unroll some of the loops. + * Some numerical constants are replaced with character literals, so the actual value is unclear. + * All of the strings used by the program have been combined into a single string literal. + * Most of the values used for the actual signal-processing all reside in one array, named `l`. This array is usually accessed at index `z` plus a constant. Accesses of this type have been rewritten from, e.g. `l[z+17]` to `17[l+z]`. `[l+z]` ends up occurring quite often, so I created the macro `a` as a shorthand. + + +### Algorithm Details + +Each tone in a DTMF signal is a combination of two frequencies. The lower frequency determines which row the digit is in, and the higher frequency determines the column. There are 4 possible row frequencies and 4 possible column frequencies. + +| | **1209 Hz** | **1336 Hz** | **1477 Hz** | **1633 Hz** | +|------------|-------------|-------------|-------------|-------------| +| **697 Hz** | 1 | 2 abc | 3 def | A | +| **770 Hz** | 4 ghi | 5 jkl | 6 mno | B | +| **852 Hz** | 7 pqrs | 8 tuv | 9 wxyz | C | +| **941 Hz** | * | 0 | # | D | + +This program determines which frequencies are present in the input by passing it through a set of 8 virtual resonators, each tuned to one of the frequencies used for DTMF. These can be implemented using only basic arithmetic, and they are able to 'select' a specific frequency from the input sound, blocking all other frequencies from reaching the output. The loudness of the sound output from each resonator can therefore be used as a measure of how much of a particular frequency was present in the input. The program then decides, over the course of one tone, which row frequency and which column frequency were most prominent. + +Tones are generated using those same resonators by providing [an impulse](https://en.wikipedia.org/wiki/Kronecker_delta#Digital_signal_processing) as input. An impulse can be thought of as consisting of sine-waves at all frequencies, and when it is put through one of the resonators, the result is a single pure sine wave. + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/giles/pi.wav b/ioccc/2020/giles/pi.wav new file mode 100644 index 0000000000000000000000000000000000000000..496de4ee9a9f865b1109967052254c85d75a93f8 Binary files /dev/null and b/ioccc/2020/giles/pi.wav differ diff --git a/ioccc/2020/giles/prog.c b/ioccc/2020/giles/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..f81ceda5f5f58ae7aa0cdbd9652ab12a0117d9ee --- /dev/null +++ b/ioccc/2020/giles/prog.c @@ -0,0 +1,70 @@ +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#include <io.h> +#include <fcntl.h> +#define X ;_setmode(_fileno(h),_O_BINARY) +#else +#define X +#endif + +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#define a [l+z] +#define m(aa) z=aa;z=z;; +#define g(g,a)memset(g,0,a); +#define e2(a,g)!fread(a,g,1,h) +#define aa(a)fprintf(stderr,"%s\n",a);return 1; +#define n(n) b=n-i;b=b<0?1+b:1-b;d[n+2]+=b>0?b*c*aa:0; +#define t(t) z=t;b=(1-6[d])*d[2]+2*17 a*0 a-1 a*d[6];1 a=0 a;0 a=b*6[d]; +#define f(f,aa) x=0; f(2)aa f(10)aa f(6)aa f(12)aa f(4)aa f(8)aa f(14)aa f(0)aa +#define j if(w){b=-1;char j=0;f(m,if(32 a>b){b=32 a;j=k[z];}if(33 a>b){b=33 a;j=k[z+1];})putchar(j);} + +const char*t= + +"Dual-tone multi-frequency signaling" +"(DTMF) is a telecommunication signaling" +"system using the voice-frequency band" + + "Invalid WAV input\0Read " + "error\0Cannot read dtmf.bin\0rb\0"+111; + int main(int m,char**f){double aa,c,d[8]={[ + 6]=--m?1:0.994,[7]=1e-4},g,i=0,l['0']={0},b, + e2=0,x;char k[':'+'s'];FILE*h;if(!(h=fopen(t+ + ')',t+'2'))){memcpy: aa(t+'A'-'$')}uint32_t p= + e2(k+'U',',')||e2(l+16,'C'+'=')||e2(k,'Q'),w=0 + ,o[2],z,n;fclose(h);if(p)goto memcpy;setvbuf(h +=m?stdout:stdin,0,_IOFBF,65536)X;uint16_t e,v; +int16_t r;if(m){m(6400*strlen(*++f))mem\ +cpy(k+'+'+'R',&z,4);z+='$';me\ +mcpy(k+'Y',&z,4);fwrite(k+'U', +',',1,h);while(**f){char*c=st\ +rchr(k,*(*f)++);g(l,'F'+':')if +(c){w=c-k;double*n=l+w%4*2;*n +=n[16];n=l+8+(w/4)%4*2;*n=n[ +16];}for(w=3200;w;--w){f(t,x ++=b*e2*49e2;)r=x;fwrite(&r,2 +,1,h);e2+=(w>1300?1:-1)*3e-2 +;e2=(e2>1?1:(e2>0?e2:0));}}} +else{ if(e2(k+'+'+'V',',')){ +fread:aa(t+18)}if( memcmp(k+ +'+'+'^',k+']',14)){ int_16t: +aa(t)}memcpy(&n,k+'+'+'n',4) +;c=16e3/n;n=c; if(n!=c)++n;c +/=n;memcpy( &v,k+43+'x',2);v +/=8; memcpy(&e,k+'+'+'v',2); +if(!e||!v||v>4)goto int_16t; +e-=v;while(!e2(k+'Q',v)){m(e +)while(z-- && getc(h)>=0);if +(v>1){memcpy(&r,k+v+'O',2);g=r/512\ +.0/'@';} else g=(unsigned char)k['Q']/128.0-1; + for(p=n;p;--p){aa=(e2-g)*p/n+g;n(0)n(1)n(2)i+= + c;if(i>=1){g(d,16)g(o,8) f(t,b=0 a-d[6]*17 a*1 + a;aa=d[6]*1 a*16 a;aa=b*b+aa*aa;x+=aa;if(aa>=d + [z/8]){o[z/8]=z/2;d[z/8]=aa;})if( (r=w?x>d[7]* + 0.45:x>d[7]*0.6)){if(!w)g(l+32,128)if(x>d[7]) + d[7]=x; /* x= (-b+sqrt(b*b-4*a*c))/(2*a); */ +++ l[16+o[1]*4+*o];}else j w=r;memmove(d+2,d+3 + ,24);--i;}}e2=g;}if(ferror(h))goto fread + ;j puts("0123456789"+10);}return 0;} diff --git a/ioccc/2020/guidelines.txt b/ioccc/2020/guidelines.txt new file mode 100644 index 0000000000000000000000000000000000000000..2a446ef0d35338155c2c9d3936584b014f2dfebc --- /dev/null +++ b/ioccc/2020/guidelines.txt @@ -0,0 +1,996 @@ +| 27th International Obfuscated C Code Contest Official Guidelines + +| Copyright (C) 2006-2019 Leonid A. Broukhis, Simon Cooper, Landon Curt Noll. + +All Rights Reserved. Permission for personal, education or non-profit use is +granted provided this this copyright and notice are included in its entirety +and remains unaltered. All other uses must receive prior permission in +writing from the contest judges. + +| This guidelines file is version 2019-06-15-v27. + +Most of the changes from the previous IOCCC guideline set +have been marked with a "|" on the left hand side of the line. + + + +ABOUT THIS FILE: + + This file contains guidelines intended to help people who wish to + submit entries to the International Obfuscated C Code Contest (IOCCC). + + This is not the IOCCC rules, though it does contain comments about + them. The guidelines should be viewed as hints and suggestions. + Entries that violate the guidelines but remain within the rules are + allowed. Even so, you are safer if you remain within the guidelines. + + You should read the current IOCCC rules, prior to submitting entries. + The rules are typically sent out with these guidelines. + + We recommend that you follow the twitter handle: + + @IOCCC + + to learn about IOCCC news, important IOCCC related alerts, IOCCC + reminders, and changes to the rules and these guidelines. + + You do not have to be a twitter user to follow @IOCCC. Non-twitter + users should access: + + https://twitter.com/ioccc + + Non-twitter users should force their browsers to reload the above URL + to be sure they are seeing the most recent tweets. + + While we try to post use news at: + + http://www.ioccc.org/index.html#news + + such postings may be delayed or obscured by slow to respond mirrors. + + +| WHAT'S NEW IN 2019/2020: + + This IOCCC runs from: + +| 2019-Dec-26 06:01:41 UTC + to: +| 2020-Mar-15 06:26:49 UTC + +| The reason for the times of day are so that key IOCCC events occur during UTC +| "prime time". Do you understand why we factored this into the rules and +| guidelines? :-) + + Until the start of this IOCCC, these rules, guidelines and iocccsize.c tool + should be considered provisional BETA versions and may be adjusted + at any time. + +| Even though the contest will start in 2019, because the contest will close +| in 2020, URLs, subject lines, and contest related email addresses use 2019. + + The IOCCC submission URL: + + https://submit.ioccc.org/ + +| The submit URL should be active on or slightly before 2020-Jan-15 12:21:37 UTC. + Please wait to submit your entries until after that time. + + The official rules, guidelines and iocccsize.c tool will be available + on the official IOCCC web site on or slightly before start of this IOCCC. + Please check the IOCCC web site "How to enter" link: + + http://www.ioccc.org/index.html#enter + + on or after the start of this IOCCC to be sure you are using the correct + versions of these items before using the IOCCC entry submission URL. + + +HINTS AND SUGGESTIONS: + + You are encouraged to examine the winners of previous contests. See + FOR MORE INFORMATION for details on how to get previous winners. + + Keep in mind that rules change from year to year, so some winning entries + may not be valid entries this year. What was unique and novel one year + might be 'old' the next year. + + An entry is usually examined in a number of ways. We typically apply + a number of tests to an entry: + + * look at the original source + * convert ANSI tri-graphs to ASCII + * C pre-process the source ignoring '#include' lines + * C pre-process the source ignoring '#define' and '#include' lines + * run it through a C beautifier + * examine the algorithm + * compile it (with flags to enable all warnings) + * execute it + + You should consider how your entry looks in each of the above tests. + You should ask yourself if your entry remains obscure after it has been + 'cleaned up' by the C pre-processor and a C beautifier. + + Your entry need not pass all of the above tests. In certain + cases, a test is not important. Entries that compete for the + 'strangest/most creative source layout' need not do as well as + others in terms of their algorithm. On the other hand, given + two such entries, we are more inclined to pick the entry that + does something interesting when you run it. + + We try to avoid limiting creativity in our rules. As such, we leave + the contest open for creative rule interpretation. As in real life + programming, interpreting a requirements document or a customer request + is important. For this reason, we often award 'worst abuse of the + rules' to an entry that illustrates this point in an ironic way. + + We do realize that there are holes in the rules, and invite entries + to attempt to exploit them. We will award 'worst abuse of the rules' + and then plug the hole next year. Even so, we will attempt to use +| the smallest plug needed, if not smaller. Or, maybe not. :-) + +| There may be less than 2^7-1 reasons why these guidelines seem obfuscated. + + Check out your program and be sure that it works. We sometimes make + the effort to debug an entry that has a slight problem, particularly + in or near the final round. On the other hand, we have seen some + of the best entries fall down because they didn't work. + + We tend to look down on a prime number printer that claims that + 16 is a prime number. If you do have a bug, you are better off + documenting it. Noting "this entry sometimes prints the 4th power + of a prime by mistake" would save the above entry. And sometimes, + a strange bug/feature can even help the entry! Of course, a correctly + working entry is best. Clever people will note that 16 might be prime + under certain conditions. Wise people, when submitting something clever + will fully explain such cleverness in their entry's remarks file. + + People who are considering to just use some complex mathematical + function or state machine to spell out something such as "hello, + world!" really really, and we do mean really, do need to be more creative. + + Ultra-obfuscated programs are, in some cases, easier to + deobfuscate than subtly-obfuscated programs. Consider using + misleading or subtle tricks layered on top of or under an + appropriate level of obfuscation. A clean looking program with + misleading comments and variable names might be a good start. + + When programs use VTxxx/ANSI sequences, they should NOT limited to a + specific terminal brand. Those programs that work in a standard xterm + are considered more portable. + +| Rule 2 (the size rule) refers to the use of an IOCCC size tool. +| The source for this tool is found at: + +| http://www.ioccc.org/2020/iocccsize.c + + To further clarify rule 2, we subdivided it into two parts, 2a and 2b. +| Your entry must satisfy BOTH the maximum size rule 2a AND your entry + must satisfy the IOCCC size tool rule 2b. + + The IOCCC size tool should be compiled as: + + cc -pedantic -Wall -Wextra -std=c11 iocccsize.c -o iocccsize + + This tool imposes a 2nd limit on C code size (rule 2b). To check your + code against the 2nd limit of rule 2, use the -i command line option. + For example: + + ./iocccsize -i < prog.c + + The IOCCC size tool, when using the -i option, may be summarized as: + + The size tool counts most C reserved words (keyword, secondary, + and selected preprocessor keywords) as 1. The size tool counts all + other octets as 1 excluding ASCII whitespace, and excluding any + ';', '{' or '}' followed by ASCII whitespace, and excluding any + ';', '{' or '}' octet immediately before the end of file. + + ASCII whitespace includes ASCII tab, ASCII space, ASCII newline, + ASCII formfeed, and ASCII carriage return. + +| When ';', '{' or '}' are within a C string, they may still not be +| counted by the IOCCC size tool. This is a feature, not a bug! + + In cases where the above summary and the algorithm implemented by + the IOCCC size tool source code conflict, the algorithm implemented + by the IOCCC size tool source code is preferred by the judges. + + There are at least 2 other reasons for selecting 2053 as the 2nd limit + besides the fact that 2053 is the next prime > 2048. These reasons + may be searched for and discovered if you are "Curios!" about 2053. :-) + Moreover, 2053 was the number of the kernel disk pack of one of the + judge's BESM-6. + + Take note that this secondary limit imposed by the IOCCC size tool + obviates some of the need to #define C reserved words in an effort + to get around the size limits of rule 2. + + Yes Virginia, that is a hint! + +| We applaud programs that do not issue warnings when compiled. +| To avoid warnings, you might be tempted to add various -Wno-foobar +| flags. Unfortunately such flags are NOT portable. Moreover, +| such flags are not consistent between different C compilers. +| Therefore we recommend that you consider one of several approaches: +| +| a) Write code that does not generate compiler warnings +| b) Do not use flags that disable compiler warnings +| c) Provide instructions (such as in your Makefile) that +| uses appropriate disable compiler warnings flags for +| both clang and gcc +| d) Do something creative + + +OUR LIKES AND DISLIKES: + + Doing masses of #defines to obscure the source has become 'old'. We + tend to 'see thru' masses of #defines due to our pre-processor tests + that we apply. Simply abusing #defines or -Dfoo=bar won't go as far + as a program that is more well rounded in confusion. + + Many C compilers dislike the following code, and so do we: + + #define d define + #d foo /* <-- don't expect this to turn into #define foo */ + + When declaring local or global variables, you should declare the type: + + int this_is_fine; + this_is_not; /* <-- Try to avoid implicit type declarations */ + + We suggest that you compile your entry with a commonly available + c11 (formerly C1X) C compiler (ISO/IEC 9899:2011). + + Do not assume that optional c11 features are supported. If you + must use an optional c11 feature, use feature test macros so + that implementations without such optional c11 features will see + an entry that is both functional and interesting. + + We like entries that have workarounds that allow someone with + an older c99 (ISO/IEC 9899:1999) compiler to be able to compile + and enjoy your entry. + + We really like "lint free" code. However lint is a toll of the past. + So try to ensure that your entry compiles warning free. If possible, + to compile compile your code using: + + -Wall -Wextra -pedantic + + For compilers, such as clang, that have the -Weverything option, try + to make your code compile warning free using: + + -Wall -Wextra -Weverything -pedantic + + If you must turn off various warnings on the compile line such as: + + ... -Wno-empty-body -Wno-return-type ... + + be sure to clearly state so in your remarks AS WELL AS in + your "how to build" / Makefile. + + All other things being equal, a program that must turn off fewer + warnings will be considered better, for certain values of better. + + Unless you clearly state otherwise in your remarks AS WELL AS in + your "how to build" / Makefile we will compile using: + + -O3 -std=c11 + + Anyone care to submit an entry that makes gratuitous use of all + of the c11 reserved words in their intended C language contexts? + NOTE: As with the use of the word Belgium, the use of certain gratuitous + c11 reserved words may be completely banned in all parts of the Galaxy, + except in one small part (ISO/IEC 9899:2011) where they might not truly + understand the implications of such words. + + http://hitchhikers.wikia.com/wiki/Belgium + http://www.bezem.de/pdf/ReservedWordsInC.pdf + + DO NOT assume that we will use gcc to compile your program. + We will first try to compile your program using Clang. + + It is much better to not use any obscure compiler flags if + you can help it. We want to discourage the use of obscure compiler + flags that would make the program less portable. + + One side effect of the above is that you cannot assume the use + of nested functions such as: + + main() { +| void please_do_not_submit_this() { +| printf("The machine that goes BING!\n"); + } +| please_do_not_submit_this(); + } + + This is because such nested functions often requires one to compile with + a flag such as -fnested-functions that is not found on some compilers. + + On 2012 July 20, the judges rescinded the encouragement of + nested functions. Such constructions, while interesting and sometimes + amusing, will have to wait until they required by a C standard that are + actually implemented in commonly used C compilers. Sorry! + +| We prefer programs that do not require a fish license: crayons and +| cat detector vans not withstanding. + + If your entry uses functions that have a variable number of + arguments, be careful. Systems implement va_list as a wide variety + of ways. Because of this, a number of operations using va_list are + not portable and must not be used: + + * assigning a non-va_list variable to/from a va_list variable + * casting a non-va_list variable into/from a va_list variable + * passing a va_list variable to a function expecting a non-va_list arg + * passing a non-va_list variable to a function expecting a va_list arg + * performing arithmetic on va_list variables + * using va_list as a structure or union + + In particular, do not treat va_list variables as if they were a char **'s. + + Avoid using <varargs.h>. Use <stdarg.h> instead. + + On 28 January 2007, the Judges rescinded the requirement that the + '#" in a C preprocessor directive must be the 1st non-whitespace octet. + + The exit() function returns void. Some broken systems have exit() + return int, your entry should assume that exit() returns a void. + +| This guideline has a change mark at the very start of this line. + + Small programs are best when they are short, obscure and concise. + While such programs are not as complex as other winners, they do + serve a useful purpose. They are often the only program that people + attempt to completely understand. For this reason, we look for + programs that are compact, and are instructional. + + While those who are used to temperatures found on dwarf planet, + (yes Virginia, dwarf planets are planets) such as Pluto might be able to + explain to the Walrus why our seas are boiling hot, the question of + whether pigs have wings is likely to remain a debatable point to most. + + One line programs should be short one line programs: say around 80 to 120 + octets long. Going well beyond 140 octets is a bit too long to be called + a one-liner in our vague opinion. + + We tend to dislike programs that: + + * are very hardware specific + * are very OS version specific + (index/strchr differences are OK, but socket/streams specific + code is likely not to be) + * dump core or have compiler warnings + (it is OK only if you warn us in the 'remark' header item) + * won't compile or run under a POSIX P1003.1/P1003.2 like systems + * depend on a utility or application not normally found on most + most POSIX P1003.1/P1003.2 like systems + * abuse the build file to get around the size limit + * obfuscate by excessive use of ANSI tri-graphs + * are longer than they need to be + * are "blob-ier" than they need to be + * are rather similar to previous winners :-( + * are too similar to previous losers :-) +| * that mandate the exclusive the use of an specific Integrated +| Development Environment (IDE) + +| In order to encourage entry portability, we dislike entries that +| fail to build unless one is using an IDE. For example, do not +| mandate that one must use Microsoft Visual Studio to compile +| your entry. Nevertheless some of the better IDEs have command-line +| interfaces to their compilers, once one learns how to invoke a shell. + +| The program must compile and link cleanly in a POSIX-like environment. +| Therefore do not assume the system has a windows.h include file: +| +| #include <windows.h> /* we dislike this include */ + + Unless you are cramped for space, or unless you are entering the + 'best one liner' category, we suggest that you format your program + in a more creative way than simply forming excessively long lines. + + At least one judge prefers to maintain the use of the leap-second + as part of the world's time standard. If your code prints time + with seconds, we prefer that your code be capable of printing the + time of day during a leap-second where the value in seconds + after the minute mark is 60. + + The "how to build" make process should not be used to try and get + around the size limit. It is one thing to make use of a several -D's +| on the compile line to help out, but it is quite another to use many + bytes of -D's in order to try and squeeze the source under the size limit. + +| Your source code, post-pre-processing, should not exceed the size +| of Windows. :-) + + The judges, as a group, have a history giving wide degree of latitude + to reasonable entries. And recently they have had as much longitudinal + variation as it is possible to have on Earth. :-) + + You should try to restrict commands used on the build file to + POSIX-like or common Un*x-like commands. You can also compile + and use your own programs. If you do, try to build and execute + from the current directory. This restriction is not a hard and + absolute one. The intent is to ensure that the building if your + program is reasonably portable. + + We prefer programs that are portable across a wide variety of Un*x-like + operating systems (i.e., Linux, GNU Hurd, BSD, Un*x, etc.). + + You are in a maze of twisty guidelines, all different. + + There are at least zero judges who think that Fideism has little + or nothing to do with the IOCCC judging process. + + Don't forget that the building of your program should be done + ***without human intervention***. So don't do things such as: + + prog: prog.c + #echo this next line requires data from standard input + cat > prog.c + ${CC} prog.c -o prog + + However, you can do something cute such as making your program + do something dumb (or cute) when it is built 'automatically'. And + when it is run with a human involved, do something more clever. + For example, one could use the build instructions: + + prog: prog.c + ${CC} prog.c -DNON_HUMAN_COMPILE -o prog + @echo "See remarks section about alternate ways to compile" + + and then include special notes in the program "remarks" for + alternate / human intervention based building. + + We want to get away from source that is simply a compact blob of + octets. Really try to be more creative than blob coding. *HINT!* + + Please do not use things like gzip to get around the size limit. + Please try to be much more creative. + + We really dislike entries that make blatant use of including + large data files to get around the source code size limit. + + We do not recommend submitting systemd source code to the IOCCC, + if nothing else because that code is likely to exceed the source code + size limit. This isn't to say that another highly compact and obfuscated + replacement of init would not be an interesting submission. + + Did we remember to indicate that programs that blatantly use + some complex state machine to do something simple are boring? + We think we did. :-) + + All generalizations are false, including this one. -- Mark Twain + + Given two versions of the same program, one that is a compact blob + of code, and the other that is formatted more like a typical C + program, we tend to favor the second version. Of course, a third + version of the same program that is formatted in an interesting + and/or obfuscated way, would definitely win over the first two! + Remember, you can submit more than one entry. See the rules for details. + + We suggest that you avoid trying for the 'smallest self-replicating' + source. The smallest, a zero byte entry, won in 1994. + + Programs that claim to be the smallest C source that does something, really + better be the smallest such program or they risk being rejected because + they do not work as documented. + + Please note that the C source below, besides lacking in obfuscation, + is NOT the smallest C source file that when compiled and run, dumps core: + + main; + + We do not like writable strings. That is, we don't want stuff like: + + char *T = "So many primes, so little time!"; + ... + T[14] = ';'; + + Please don't make use of this feature, even if your system allows it. + However, initialized char arrays are OK to write over. This is OK: + + char b[] = "Is this OK"; + b[9] = 'K'; + +| There are more than one typos in this very sentence. + + X client entries should be as portable as possible. Entries that + adapt to a wide collection of environments will be favored. For + example, don't depend on a particular type or size of display. + Don't assume the use of a particular browser. Instead assume a + generic browser that forms to a widely used W3C standard. + Don't assume a particular sound sub-system or video driver is installed + in the OS. Instead, make use of a well known and widely available open + source program (one that actually works) to display audio/visual data. + + X client entries should avoid using X related libraries and + software that is not in wide spread use. + + This is the only guideline that contains the word fizzbin. +| However, do you know how to play fizzbin? You do?!? (Except on Tuesday) + + We don't like entries that use proprietary toolkits such as the M*tif, + Xv*ew, or OpenL*ok toolkits, since not everyone has them. Use of an + open source toolkit that is widely and freely available instead. + +| The previous guideline in this spot has been replaced by this guideline: +| ------------------------------------------------------------------------ + + X client entries should not to depend on particular items on + .Xdefaults. If you must do so, be sure to note the required lines + in the program "remarks". They should also not depend on any + particular window manager. + + Try to avoid entries that play silent sound segments or play the + Happy Birthday song; music that some people believe is copyrighted + (even if such copyrights appear to be bogus and/or blatant abuses of + the copyright system). + + While we recognize that UN*X is not a universal operating system, the + contest does have a bias towards such systems. In an effort to expand + the scope of the contest, we phrase our bias in terms of POSIX P1003.1 + and P1003.2 standards. This will allow certain non-UN*X OS users to + submit entries. On the other hand, this is a guideline and not a rule. + We will not reject an entry based on some POSIX technicality. + + When dealing with OS and application environments, we suggest that you + be reasonable with a nod towards vanilla UN*X-like systems. POSIX will + evolve but not as much as the contest. + + You very well might not be completely prohibited from failing to not + partly misunderstand this particular guideline, but of course we could +| not possibly comment. Nevertheless, you are neither prohibited, nor are +| you required to determine that this or the previous sentence is either false +| and/or misleading. Therefore, it might be wise for you to not fail to consider +| to do so, accordingly. Thank you. + + Any complaints about the above guideline could be addressed to the + Speaker of the House of Commons, or to the speaker of your national +| parliament should you have one. + + We like programs that: + + * are as concise and small as they need to be + * do something at least quasi-interesting + * are portable + * are unique or novel in their obfuscation style + * MAKE USE OF A NUMBER OF DIFFERENT TYPES OF OBFUSCATION <== HINT!! + * make us laugh and/or throw up :-) (humor really helps!) + * make us want to eat good chocolate. + + Some types of programs can't excel (anti-tm) in some areas. Your + program doesn't have to excel in all areas, but doing well in several + areas really does help. + + You are better off explaining what your entry does in the program + "remarks" section rather than leaving it obscure for the judges + as we might miss something and/or be too tired to notice. + +| Please avoid this specific individual guideline, if at all possible. + + We freely admit that interesting, creative or humorous comments in + the program "remarks" help your chances of winning. If you had to + read so many twisted entries, you too would enjoy a good laugh or two. + We think the readers of the contest winners do as well. We do read + the program "remarks" during the judging process, so it is worth your + while to write remarkable program "remarks". + + We dislike C code with trailing control-M's (\r or \015) that results + in compilation failures. Some non-Un*x/non-Linux tools such as + MS Visual C and MS Visual C++ leave trailing control-M's on lines. + Users of such tools should strip off such control-M's before submitting + their entries. In some cases tools have a "Save As" option that will + prevent such trailing control-M's being added. + + One should restrict libcurses to portable features found on BSD + or Linux curses. + + Rule 13 states any C source that fails to compile because of unescaped + octets with the high bit set (octet value >= 128) will be rejected. + Instead of unescaped octets, you should use \octal or \hex escapes: + + /* 123456789 123456789 123456789 123456 */ + char *foo = "This string is 36 octets in length \263"; + /* This octet requires 4 octets of source ^^^^ */ + if (strlen(foo) == 36) printf("foo is 36 octets plus a final NUL\n"); + else printf("This code should not print this message\n"); + + It is a very good idea to, in your remarks file, tell us why you + think your entry is obfuscated. This is particularly true if + your entry is has some very subtle obfuscations that we might + otherwise overlook. <<-- Hint! + + Anyone can format their code into a dense blob. A really clever + author will try format their entry using a "normal" formatting style + such that at first glance (if you squint and don't look at the details) + the code might pass for non-obfuscated C. Deceptive comments, + and mis-leading formatting, in some cases, may be a plus. On the + other hand, a misleading code style requires more source bytes. + + If you do elect to use misleading formatting and comments, we + suggest you remark on this point in your remarks where you talk + about why you think your entry is obfuscated. On the other hand, + if you are pushing up against the size limits, you may be forced + into creating a dense blob. Such are the trade offs that obfuscators face! + + We prefer code that can run on either a 64-bit or 32-bit processor. + However, it is unwise to assume it will run on an i386 or x86 architecture. + + We believe that Mark Twain's remark: + + Get your facts first, then you can distort them as you please. + + is a good guideline for those writing code for the IOCCC. + + The IOCCC size tool source, iocccsize.c, is not an original work, +| unless you are Anthony C Howe, in which case it is original! +| Submitting source that uses the content iocccsize.c, unless you are +| Anthony C Howe, might run the risk of violating rule 7. + + Rule 7 does not prohibit you from writing your own obfuscated IOCCC size tool. + However if you do, you might wish to make your tool do something more + interesting than simply implementing the IOCCC size tool algorithm. + + While programs that only run in a specific word size are OK. If you have + to pick, choose a 64-bit word size. + + If we are feeling ornery we might choose to compile your program + for running on an Arduino or a PDP-11. Heck, should we ever find + an emulator of 60-bit CDC Cyber CPU running a POSIX-like OS, we + might just try your entry on that emulator as well :-) + + If your entry MUST run only in 32-bit mode on an Intel processor, add the + following compiler flag: + + -arch i386 + + to your "how to build" make compile line. For example: + + prog: prog.c + ${CC} prog.c -arch i386 -o prog + + Be even more creative! + + If there are limitations in your entry, you are highly encouraged + to note such limitations in your remarks file. For example if your + entry factors values up to a certain size, you might want to state: + + This entry factors values up 2305567963945518424753102147331756070. + Attempting to factor larger values will produce unpredictable results. + + The judges might try to factor the value -5, so you want to might state: + + This entry factors positive values up 2305567963945518424753102147331756070. + Attempting to factor large values will produce unpredictable results. + + However the judges might try to also factor 0, so you want to might state: + + This entry factors values between 1 and 2305567963945518424753102147331756070. + Attempting to factor values outside that range will produce unpredictable results. + + Moreover the try to also factor 3.5 or 0x7, or Fred, so you want to might state: + + This entry factors integers between 1 and 2305567963945518424753102147331756070. + Attempting to factor anything else will produce unpredictable results. + + You entry might be better off catching the attempt to factor bogus values + and doing something interesting. So you might want to code accordingly and state: + + This entry factors integers between 1 and 2305567963945518424753102147331756070. + Attempting to factor anything else will cause the program to insult your + pet fish Eric. + + The judges might not have a pet fish named Eric, so might want to state: + + This entry factors integers between 1 and 2305567963945518424753102147331756070. + Attempting to factor anything else will cause the program to insult your + pet fish Eric, or in the case that you lack such a pet, will insult the + pet that you do not have. + + When all other things are equal, an entry with fewer limitation will be judged + better than an entry with lots of limitations. So you might want to code accordingly + and state: + + This entry attempts to a factor value of any size provided that the program + is given enough time and memory. If the value is not a proper integer, the + program will insult a fish named Eric, even if such a fish does not exist. + + +ABUSING THE RULES: + + Legal abuse of the rules is somewhat encouraged. Legal rule abuse may + involve, but is not limited to, doing things that are technically + allowed by the rules and yet do not fit the spirit of what we intended + to be submitted. + + Legal rule abuse is encouraged to help promote creativity. Rule abuse + entries, regardless of if they receive an award, result in changes to + the next year's rules and guidelines. + + Legal abuse of the rules is NOT an invitation to violate the rules. + An entry that violates the rules in the opinion of the judges, WILL be + disqualified. RULE ABUSE CARRIES A CERTAIN LEVEL OF RISK! If you + have an entry that might otherwise be interesting, you might want to + submit two versions; one that does not abuse the rules and one that + does. + + If you intend to abuse the rules, indicate so in the program + "remarks". You must try to justify why you consider your rule abuse + to be allowed under the rules. That is, you must plead your case as + to why your entry is valid. Humor and/or creativity help plead a + case. + + Abusing the web submission procedure tends to annoy us more + than amuse us. Spend your creative energy on content of your + entry rather than on the submission process itself. + + We are often asked why the contest rules and guidelines seem too + strange or contain mistakes, flaws or grammatical errors. One reason + is that we sometimes make genuine mistakes. But in many cases such + problems, flaws or areas of confusion are deliberate. Changes to + rules and guidelines in response to rule abuses, are done in a minimal + fashion. Often we will deliberately leave behind holes (or introduce + new ones) so that future rule abuse may continue. A cleaver author + should be able to read them and "drive a truck through the holes" in + the rules and guidelines. + + At the risk of stating the obvious, this contest is a parody of the + software development process. The rules and guidelines are only a + small part of the overall contest. Even so, one may think the contest + rules and guideline process as a parody of the sometimes tragic + mismatch between what a customer (or marketing) wants and what + engineering delivers. Real programmers must face obfuscated + and sometimes conflicting specifications and requirements from marketing, + sales, product management an even from customers themselves on a + all too regular basis. This is one of the reasons why the rules and + guidelines are written in obfuscated form. + + +JUDGING PROCESS: + + Entries are judged by Leonid A. Broukhis, Simon Cooper, Landon Curt Noll. + + Each entry submitted is given a random id number and subdirectory. The + entry files including, but not limited to prog.c, Makefile (that we + form from around your "how to build" information), as well as any + data files that you submit are all placed under their own directory. + stored and judged from this directory. + + Any information about the authors is not read by the judges until + the judging process is complete, and then only from entries that have + won an award. Because we do not read this information for entries that + do not win, we do not know who did not win. + + The above process helps keep us biased for/against any one particular + individual. Therefore you MUST refrain from putting any information + that reveals your identity in your entry. + + Now some people point out that coding style might reveal the information + about the others. However we consider this to be simply circumstantial + and outside the scope of the above paragraph. + + Some people, in the past, have attempted to obfuscate their identity by + including comments of famous Internet personalities such as Peter Honeyman + (http://www.citi.umich.edu/u/honey/). The judges are on to this + trick and therefore consider any obfuscated source or data file + claiming to be from Honeyman to not be form Honeyman. This of course + creates an interesting paradox known as the "obfuscated Peter Honeyman + paradox". Should Peter Honeyman actually submit an obfuscated entry, + he alone is excluded from the above, as we will likely believe + it just another attempt at confusion. This guideline is known + as the "Peter Honeyman is exempt" guideline. + + BTW: None of the entries claiming to be from Peter Honeyman have ever + won an award. So it is theoretically possible that Peter Honeyman + did submit an entry in the past. In the past, Peter had denied + submitting anything to the IOCCC. Perhaps those entries were + submitted by one of his students? + + Hopefully we are very CLEAR on this point! The rules now strongly state: + PLEASE DO NOT put a name of an author, in an obvious way, into your + source code, remarks, data files, etc. The above "Peter Honeyman is + exempt" not withstanding. + + We seemed to have digressed again ... :-) Returning to the judging process: + + We prefer to be kept in the dark as much as you are until the final + awards are given. We enjoy the surprise of finding out in the end, + who won and where they were from. + + We attempt to keep all entries anonymous, unless they win an award. + Because the main 'prize' of winning is being announced, we make all + attempts to send non-winners into oblivion. We remove all non-winning + files, and shred all related paper. By tradition, we do not even + reveal the number of entries that we received. + + During the judging process. a process that spans multiple sessions + over a few weeks, post general updates from our @IOCCC twitter account. + + Once we have selected the winners, for each category we will tweet: + + category name + name(s) of the authors (or anonymous if requested) + twitter handle(s) (if provided and if anonymity was not requested) + country code(s) of the author(s) + + After the initial announcement, we attempt to send Email to the + authors of the winning entries. One reason we do this is to give + the authors a chance to comment on the way we have presented their + entry. They are given the chance to correct mistakes and typos. We + often accept their suggestions/comments about our remarks as well. + This is done prior to posting the winners to the wide world. + + Judging consists of a number of elimination rounds. During a round, + the collection of entries are divided into two roughly equal piles; + the pile that advances on to the next round, and the pile that does + not. We also re-examine the entries that were eliminated in the + previous round. Thus, an entry gets at least two readings. + + A reading consists of a number of actions: + + * reading the "how to build" information and forming a Makefile + * reading prog.c, the C source + * reviewing the "remarks" information + * briefly looking any any supplied data files + * passing the source thru the C pre-processor + skipping over any #include files + * performing a number of C beautify/cleanup edits on the source + * passing the beautified source thru the C pre-processor + skipping over any #include files + * compiling/building the source + * running the program + * Doing other things that only IOCCC judges know about :-) + + In later rounds, other actions are performed including performing + miscellaneous tests on the source and binary. + +! This is the very guideline that goes, BING! + + Until we reduce the stack of entries down to about 25 entries, entries + are judged on an individual basis. An entry is set aside because it + does not, in our opinion, meet the standard established by the round. + When the number of entries thins to about 25 entries, we begin to form + award categories. Entries begin to compete with each other for awards. + An entry will often compete in several categories. + + The actual award category list will vary depending on the types of entries + we receive. A typical category list might be: + + * best small one line program (see above about one line programs) + * best small program + * strangest/most creative source layout + * most useful obfuscated program + * best game that is obfuscated + * most creatively obfuscated program + * most deceptive C code (code with deceptive comments and source code) + * best X client (see OUR LIKES AND DISLIKES) + * best abuse of ISO C or ANSI C standard (see above about compilers) + * best abuse of the C preprocessor + * worst abuse of the rules + * (anything else so strange that it deserves an award) + + We do not limit ourselves to this list. For example, a few entries are so + good/bad that they are declared winners at the start of the final round. + We will invent awards categories for them, if necessary. + + In the final round process, we perform the difficult tasks of + reducing the remaining entries (typically about 25) down to to about + half that number: declaring those remaining to be winners. + + Often we are confident that the entries that make it into + the final round are definitely better than the ones that do not + make it. The selection of the winners out of the final round, is + less clear cut. + + Sometimes a final round entry is good enough to win, but is beat out + by a similar, but slightly better entry. For this reason, it is + sometimes worthwhile to re-enter an improved version of an entry + that failed to win in a previous year. This assumes, of course, + that the entry is worth improving in the first place! + + More than one IOCCC judge has been known to bribe another IOCCC judge + into voting for a winning entry by offering a bit high quality chocolate. + This technique is highly discouraged for use by non-IOCCC judges. + + More often than not, we select a small entry (usually one line), a + strange/creative layout entry. We sometimes also select an + entry that abuses the contest guidelines in an interesting way, + or that stretches the content rules that while legal, is + nevertheless goes against the intent of the rules. + + In the end, we traditionally pick one entry as 'best'. Sometimes such + an entry simply far exceeds any of the other entries. More often, the + 'best' is picked because it does well in a number of categories. + + In years past, we renamed the winning entry from prog.c to a + name related to the submitter(s) names. This is no longer done. + Winning source is called prog.c A compiled binary is called prog. + + +ANNOUNCEMENT OF WINNERS: + + The judges will tweet initial announcement of who won, the name + of their award, and a very brief description of the winning entry + from the @IOCCC twitter handle. Non-twitter users should visit: + + https://twitter.com/ioccc + + Non-twitter users should force their browsers to reload the above URL + to be sure they are seeing the most recent tweets. + + The judges will then post an initial announcement of who won, the name + of their award, and a very brief description of the winning entry + on the IOCCC web site: + + http://www.ioccc.org/whowon.html + + We will also attempt to submit a brief announcement story to /.: + + http://slashdot.org + + that, depending on the willingness of the /. editors, may be posted + to their site at the same time. + + Note that initial announcement will NOT contain source. This is because + the winning authors are given a chance to review the judges comments, + and test our Makefile. This review process typically takes a few weeks. + + Sometime after the initial announcement, and once the the review + by the winners has been completed, the winning source will be + posted to the IOCCC web site: + + http://www.ioccc.org/years.html + + NOTE: previous winners are available at that URL + + We will also tweet, via @IOCCC, when the winning source is available. + + It is pointless to ask the IOCCC judges how many entries we receive. + Other government TLA or FLA snooping organizations are prohibited from + either confirming, denying or revealing any knowledge of this data point. + + Often, winning entries are published in selected magazines from around + the world. Winners have appeared in books ("The New Hackers Dictionary") + and on T-Shirts. More than one winner has been turned in a tattoo! + + Last, but not least, winners receive international fame and flames! :-) + + +FOR MORE INFORMATION: + + You may contact the judges by sending Email to the following address: + +| q.2020@ioccc.org (do not submit entries to this address) + +| You must include the words 'ioccc 2020 question' in the subject of your + Email message when sending Email to the judges. + + Questions and comments about the contest are welcome. Comments about + confusing rules and guidelines are also welcome. + + The rules and the guidelines may (and often do) change from year to + year. You should be sure you have the current rules and guidelines + prior to submitting entries. + + Check out the IOCCC Web page: + + http://www.ioccc.org + + It has rules, guidelines and winners of previous contests (1984 to date). + + For the updates and breaking IOCCC news, you are encouraged to follow + the twitter handle: + + @IOCCC + + You do not have to be a twitter user to follow @IOCCC. Non-twitter + users should access: + + https://twitter.com/ioccc + + Non-twitter users should force their browsers to reload the above URL + to be sure they are seeing the most recent tweets. + +Leonid A. Broukhis +Simon Cooper +chongo (Landon Curt Noll) /\cc/\ diff --git a/ioccc/2020/iocccsize-test.sh b/ioccc/2020/iocccsize-test.sh new file mode 100755 index 0000000000000000000000000000000000000000..f3e38a39b1a5ace29bb52d4eb7a6016c5044f2fb --- /dev/null +++ b/ioccc/2020/iocccsize-test.sh @@ -0,0 +1,385 @@ +#!/usr/bin/env bash +# +# iocccsize-test.sh - IOCCC Size Tool Tests +# +# "You are not expected to understand this" :-) +# +# This IOCCC size tool source file is version 2019-06-20-v27. +# +# Public Domain 1992, 2015, 2019 by Anthony Howe. All rights released. +# With IOCCC minor mods in 2019 by chongo (Landon Curt Noll) ^oo^ + +export PATH='/bin:/usr/bin:/usr/local/bin:/usr/pkg/bin' +export ENV='' +export CDPATH='' +export LANG=C + +usage() +{ + echo 'usage: iocccsize-test.sh [-bv][-t tool]' + exit 2 +} + +__tool="./iocccsize" +__verbose=false + +while getopts 'bvt:' opt; do + case "$opt" in + (b) + __build="distclean" + ;; + (v) + __verbose=true + __tool_args="-v" + ;; + (t) + __tool="$OPTARG" + ;; + (*) + usage + esac +done +shift $(($OPTIND - 1)) +#if [ $# -lt 1 ]; then +# usage +#fi + +make -f iocccsize.mk ${__build} all + +if [ ! -d test ]; then + mkdir test +fi + +get_wc() +{ + typeset file="$1" + typeset field="$2" + wc $file | sed -e's/^ *//; s/ */ /g' | cut -d' ' -f$field +} + +test_size() +{ + typeset file="test/$1" + typeset expect="$2" + typeset gross_count + typeset got + + got=$($__tool $__tool_args <$file 2>&1 >/dev/null) + if $__verbose ; then + gross_count=$(echo $got | cut -d' ' -f2) + bytes=$(get_wc $file 3 $filter) + if [ $gross_count != $bytes ]; then + echo "FAIL $file: got $gross_count != wc $bytes" + return + fi + else + got=$(echo $got | cut -d' ' -f1) + expect=$(echo $expect | cut -d' ' -f1) + fi + if [ "$expect" = "$got" ]; then + echo "-OK- $file: $got" + else + echo "FAIL $file: got $got != expect $expect" + fi +} + +####################################################################### + +cat <<EOF >test/splitline0.c +#define FOO \\ + int a = 666; +FOO; +EOF +test_size splitline0.c "19 36 1" + +####################################################################### + +cat <<EOF >test/comment0.c +// comment one line "with a comment string" inside +int x; +EOF +test_size comment0.c "44 58 1" + +####################################################################### + +cat <<EOF >test/comment1.c +/* comment block same line 'with a comment string' */ +int x; +EOF +test_size comment1.c "46 61 1" + +####################################################################### + +cat <<EOF >test/comment2.c +/* +comment block +multiline +*/ +int x; +EOF +test_size comment2.c "27 37 1" + +####################################################################### + +cat <<EOF >test/comment3.c +a//foo +EOF +test_size comment3.c "6 7 0" + +####################################################################### + +cat <<EOF >test/comment4.c +/*/ int if for /*/ +EOF +test_size comment4.c "14 19 0" + +####################################################################### + +cat <<EOF >test/comment5.c +'"' "/*" foobar "*/" +EOF +test_size comment5.c "17 21 0" + +####################################################################### + +cat <<EOF >test/comment6.c +char str[] = "string /* with */ comment"; +EOF +test_size comment6.c "30 42 1" + +####################################################################### + +cat <<EOF >test/comment7.c +// comment with backslash newline \\ +int a = 666; +EOF +test_size comment7.c "37 49 0" + +####################################################################### + +cat <<EOF >test/quote0.c +char str[] = "and\"or"; +EOF +test_size quote0.c "16 24 1" + +####################################################################### + +cat <<EOF >test/quote1.c +char squote = '\''; +EOF +test_size quote1.c "12 20 1" + +####################################################################### + +cat <<EOF >test/quote2.c +char str[] = "'xor'"; +EOF +test_size quote2.c "14 22 1" + +####################################################################### + +cat <<EOF >test/digraph.c +char str<::> = "'xor'"; +EOF +test_size digraph.c "14 24 1" + +####################################################################### + +cat <<EOF >test/trigraph0.c +char str??(??) = "'xor'"; +EOF +test_size trigraph0.c "14 26 1" + +####################################################################### + +# Example from https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C +cat <<EOF >test/trigraph1.c +// Will the next line be executed????????????????/ +int a = 666; +EOF +test_size trigraph1.c "49 64 0" + +####################################################################### + +# Example from https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C +cat <<EOF >test/trigraph2.c +/??/ +* A comment *??/ +/ +EOF +test_size trigraph2.c "12 24 0" + +####################################################################### + +cat <<EOF >test/trigraph3.c +#define FOO ??/ + int a = 666; +FOO; +EOF +test_size trigraph3.c "19 38 1" + +####################################################################### + +cat <<EOF >test/main0.c +int +main(int argc, char **argv) +{ + return 0; +} +EOF +test_size main0.c "22 47 4" + +####################################################################### + +cat <<EOF >test/hello.c +#include <stdio.h> + +int +main(int argc, char **argv) +{ + (void) printf("Hello world!\n"); + return 0; +} +EOF +test_size hello.c "58 101 6" + +####################################################################### + +# Digraph for #include and curlys. Digraphs are tokens and are not +# translated like trigraphs. +cat <<EOF >test/hello_digraph.c +%: include <stdio.h> + +int +main(int argc, char **argv) +<% + (void) printf("Hello world!\n"); + return 0; +%> +EOF +test_size hello_digraph.c "60 108 6" + +####################################################################### + +# Trigraph for #include and curlys. Trigraphs are translated, unlike +# digraphs which are tokens. +cat <<EOF >test/hello_trigraph.c +??= include <stdio.h> + +int +main(int argc, char **argv) +??< + (void) printf("Hello world!\n"); + return 0; +??> +EOF +test_size hello_trigraph.c "58 111 6" + +####################################################################### + +cat <<EOF >test/include0.c +# include <stdio.h> +EOF +test_size include0.c "10 21 1" + +####################################################################### + +cat <<EOF >test/include1.c +# include <stdio.h> +#/*hi*/include <ctype.h> +EOF +test_size include1.c "26 46 2" + +####################################################################### + +cat <<EOF >test/curly0.c +char str = "{ curly } "; +EOF +test_size curly0.c "12 25 1" + +####################################################################### + +# No spaces after curly braces in array initialiser. +cat <<EOF >test/curly1.c +#include <stdlib.h> + +#define STRLEN(s) (sizeof (s)-1) + +typedef struct { + size_t length; + const char *word; +} Word; + +Word list[] = { + {STRLEN("abutted curly"), "abutted curly"}, + {0, NULL} +}; +EOF +test_size curly1.c "119 192 6" + +####################################################################### + +# Spaces after curly braces in array initialiser. +cat <<EOF >test/curly2.c +#include <stdlib.h> + +#define STRLEN(s) (sizeof (s)-1) + +typedef struct { + size_t length; + const char *word; +} Word; + +Word list[] = { + { STRLEN("spaced curly"), "spaced curly"} , + { 0, NULL} +} ; +EOF +test_size curly2.c "113 196 6" + +####################################################################### + +cat <<EOF >test/semicolon0.c +char str = "; xor; "; +EOF +test_size semicolon0.c "10 22 1" + +####################################################################### + +# Spaces after semicolons in for( ; ; ). +cat <<EOF >test/semicolon1.c +#include <stdio.h> + +int +main(int argc, char **argv) +{ + int i; + for (i = 0; i < 3; i++) { + (void) printf("%d\n", i); + } + return 0; +} +EOF +test_size semicolon1.c "65 133 8" + +####################################################################### + +# No spaces after semicolons in for(;;). +cat <<EOF >test/semicolon2.c +#include <stdio.h> + +int +main(int argc, char **argv) +{ + int i; + for (i=0;i<3;i++) { + (void) printf("%d\n", i); + } + return 0; +} +EOF +test_size semicolon2.c "67 127 8" + +####################################################################### +# END +####################################################################### diff --git a/ioccc/2020/iocccsize.c b/ioccc/2020/iocccsize.c new file mode 100644 index 0000000000000000000000000000000000000000..4e74f87d5a63ecce59ac260ca5d67add1c58385a --- /dev/null +++ b/ioccc/2020/iocccsize.c @@ -0,0 +1,477 @@ +/* + * iocccsize - IOCCC Source Size Tool + * + * "You are not expected to understand this" :-) + * + * Public Domain 1992, 2015, 2018, 2019 by Anthony Howe. All rights released. + * With IOCCC minor mods in 2019 by chongo (Landon Curt Noll) ^oo^ + * + * SYNOPSIS + * + * iocccsize [-ihv] < input + * + * -i ignored for backward compatibility + * -h print usage message in stderr and exit + * -v turn on some debugging to stderr; -vv or -vvv for more + * + * The source is written to stdout, with possible translations ie. trigraphs. + * The IOCCC net count rule 2b is written to stderr; with -v, net count (2b), + * gross count (2a), number of keywords counted as 1 byte; -vv or -vvv write + * more tool diagnostics. + * + * DESCRIPION + * + * Reading a C source file from standard input, apply the IOCCC + * source size rules as explained in the Guidelines. The source + * code is passed through on standard output. The source's net + * length is written to standard error; with -v option the net + * length, gross length, and matched keyword count are written. + * + * The entry's gross size in bytes must be less than equal to 4096 + * bytes in length. + * + * The entry's net size in bytes must be less than equal to 2053 + * bytes (first prime after 2048). The net size is computed as + * follows: + * + * The size tool counts most C reserved words (keyword, secondary, + * and selected preprocessor keywords) as 1. The size tool counts all + * other octets as 1 excluding ASCII whitespace, and excluding any + * ';', '{' or '}' followed by ASCII whitespace, and excluding any + * ';', '{' or '}' octet immediately before the end of file. + */ + +#define DIGRAPHS +#define TRIGRAPHS + +/* + * IOCCC Judge's remarks: + * + * This code contains undocumented features. On the other hand, this code + * is RTFS (for certain values of RTFS). One might say that this code + * perfectly documents itself. :-) + * + * Many thanks to Anthony Howe for taking the time to put his OCD + * (Obfuscated Coding Determination) into this code! + */ + +/* + * HINT: The algorithm implemented by this code may or not be obfuscated. + * The algorithm may not or may appear to be obfuscated. + * + * In particular: + * + * We did not invent the algorithm. + * The algorithm consistently finds Obfuscation. + * The algorithm killed Obfuscation. + * The algorithm is banned in C. + * The algorithm is from Bell Labs in Jersey. + * The algorithm constantly finds Obfuscation. + * This is not the algorithm. + * This is close. + */ + +#include <err.h> +#include <ctype.h> +#include <getopt.h> +#include <string.h> +#include <stdio.h> + +#define WORD_BUFFER_SIZE 64 +#define MAX_SIZE 4096 /* IOCCC Rule 2a */ +#define MAX_COUNT 2053 /* IOCCC Rule 2b */ +#define STRLEN(s) (sizeof (s)-1) + +#define NO_COMMENT 0 +#define COMMENT_EOL 1 +#define COMMENT_BLOCK 2 + +static char usage[] = +"usage: iocccsize [-ihv] < prog.c\n" +"\n" +"-i\t\tignored for backward compatibility\n" +"-h\t\tprint usage message in stderr and exit\n" +"-v\t\tturn on some debugging to stderr; -vv or -vvv for more\n" +"\n" +"The source is written to stdout, with possible translations ie. trigraphs.\n" +"The IOCCC net count rule 2b is written to stderr; with -v, net count (2b),\n" +"gross count (2a), number of keywords counted as 1 byte; -vv or -vvv write\n" +"more tool diagnostics.\n" +"\n" +"Version: 2019-06-20-v27" +; + +static int debug; +static char *out_fmt = "%lu\n"; + +/* + * C reserved words, plus a few #preprocessor tokens, that count as 1 + * + * NOTE: For a good list of reserved words in C, see: + * + * http://www.bezem.de/pdf/ReservedWordsInC.pdf + * + * by Johan Bezem of JB Enterprises: + * + * See http://www.bezem.de/en/ + */ +typedef struct { + size_t length; + const char *word; +} Word; + +static Word cwords[] = { + /* Yes Virginia, we left #define off the list on purpose! */ + { STRLEN("#elif"), "#elif" } , + { STRLEN("#else"), "#else" } , + { STRLEN("#endif"), "#endif" } , + { STRLEN("#error"), "#error" } , + { STRLEN("#ident"), "#ident" } , + { STRLEN("#if"), "#if" } , + { STRLEN("#ifdef"), "#ifdef" } , + { STRLEN("#ifndef"), "#ifndef" } , + { STRLEN("#include"), "#include" } , + { STRLEN("#line"), "#line" } , + { STRLEN("#pragma"), "#pragma" } , + { STRLEN("#sccs"), "#sccs" } , + { STRLEN("#warning"), "#warning" } , + + { STRLEN("_Alignas"), "_Alignas" } , + { STRLEN("_Alignof"), "_Alignof" } , + { STRLEN("_Atomic"), "_Atomic" } , + { STRLEN("_Bool"), "_Bool" } , + { STRLEN("_Complex"), "_Complex" } , + { STRLEN("_Generic"), "_Generic" } , + { STRLEN("_Imaginary"), "_Imaginary" } , + { STRLEN("_Noreturn"), "_Noreturn" } , + { STRLEN("_Pragma"), "_Pragma" } , + { STRLEN("_Static_assert"), "_Static_assert" } , + { STRLEN("_Thread_local"), "_Thread_local" } , + + { STRLEN("alignas"), "alignas" } , + { STRLEN("alignof"), "alignof" } , + { STRLEN("and"), "and" } , + { STRLEN("and_eq"), "and_eq" } , + { STRLEN("auto"), "auto" } , + { STRLEN("bitand"), "bitand" } , + { STRLEN("bitor"), "bitor" } , + { STRLEN("bool"), "bool" } , + { STRLEN("break"), "break" } , + { STRLEN("case"), "case" } , + { STRLEN("char"), "char" } , + { STRLEN("compl"), "compl" } , + { STRLEN("const"), "const" } , + { STRLEN("continue"), "continue" } , + { STRLEN("default"), "default" } , + { STRLEN("do"), "do" } , + { STRLEN("double"), "double" } , + { STRLEN("else"), "else" } , + { STRLEN("enum"), "enum" } , + { STRLEN("extern"), "extern" } , + { STRLEN("false"), "false" } , + { STRLEN("float"), "float" } , + { STRLEN("for"), "for" } , + { STRLEN("goto"), "goto" } , + { STRLEN("if"), "if" } , + { STRLEN("inline"), "inline" } , + { STRLEN("int"), "int" } , + { STRLEN("long"), "long" } , + { STRLEN("noreturn"), "noreturn" } , + { STRLEN("not"), "not" } , + { STRLEN("not_eq"), "not_eq" } , + { STRLEN("or"), "or" } , + { STRLEN("or_eq"), "or_eq" } , + { STRLEN("register"), "register" } , + { STRLEN("restrict"), "restrict" } , + { STRLEN("return"), "return" } , + { STRLEN("short"), "short" } , + { STRLEN("signed"), "signed" } , + { STRLEN("sizeof"), "sizeof" } , + { STRLEN("static"), "static" } , + { STRLEN("static_assert"), "static_assert" } , + { STRLEN("struct"), "struct" } , + { STRLEN("switch"), "switch" } , + { STRLEN("thread_local"), "thread_local" } , + { STRLEN("true"), "true" } , + { STRLEN("typedef"), "typedef" } , + { STRLEN("union"), "union" } , + { STRLEN("unsigned"), "unsigned" } , + { STRLEN("void"), "void" } , + { STRLEN("volatile"), "volatile" } , + { STRLEN("while"), "while" } , + { STRLEN("xor"), "xor" } , + { STRLEN("xor_eq"), "xor_eq" } , + + { 0, NULL } +}; + +static Word * +find_member(Word *table, const char *string) +{ + Word *w; + for (w = table; w->length != 0; w++) { + if (strcmp(string, w->word) == 0) { + return w; + } + } + return NULL; +} + +static int +read_ch(FILE *fp) +{ + int ch; + + while ((ch = fgetc(fp)) != EOF && ch == '\r') { + /* Discard bare CR and those part of CRLF. */ + } + if (ch == '\0' || 128 <= ch) { + errx(1, "NUL or non-ASCII characters"); + } + + return ch; +} + +static void +rule_count(FILE *fp) +{ + char word[WORD_BUFFER_SIZE]; + size_t gross_count = 0, net_count = 0, keywords = 0, wordi = 0; + int ch, next_ch, quote = 0, escape = 0, is_comment = NO_COMMENT; + + while ((ch = read_ch(fp)) != EOF) { + /* Future gazing. */ + next_ch = read_ch(fp); + +#ifdef TRIGRAPHS + if (ch == '?' && next_ch == '?') { + /* ISO C11 section 5.2.1.1 Trigraph Sequences */ + const char *t; + static const char trigraphs[] = "=#([)]'^<{!|>}-~/\\"; + + ch = fgetc(fp); + for (t = trigraphs; *t != '\0'; t += 2) { + if (ch == t[0]) { + /* Mapped trigraphs count as 1 byte. */ + next_ch = fgetc(fp); + gross_count += 2; + ch = t[1]; + break; + } + } + + /* Unknown trigraph, push back the 3rd character. */ + if (*t == '\0') { + if (ch != EOF && ungetc(ch, fp) == EOF) { + errx(1, "ungetc error: bad \?\?%c trigraph", ch); + } + ch = '?'; + } + } +#endif + if (ch == '\\' && next_ch == '\n') { + /* ISO C11 section 5.1.1.2 Translation Phases + * point 2 discards backslash newlines. + */ + gross_count += 2; + continue; + } + + if (next_ch != EOF && ungetc(next_ch, fp) == EOF) { + /* ISO C ungetc() guarantees one character (byte) pushback. + * How does that relate to UTF8 and wide-character library + * handling? An invalid trigraph results in 2x ungetc(). + */ + errx(1, "ungetc error: @SirWumpus goofed"); + } + + /* Within quoted string? */ + if (quote != 0) { + /* Escape _this_ character. */ + if (escape) { + escape = 0; + } + + /* Escape next character. */ + else if (ch == '\\') { + escape = 1; + } + + /* Close matching quote? */ + else if (ch == quote) { + quote = 0; + } + } + + /* Within comment to end of line? */ + else if (is_comment == COMMENT_EOL && ch == '\n') { + if (debug > 1) { + (void) fprintf(stderr, "~~NO_COMMENT\n"); + } + is_comment = NO_COMMENT; + } + + /* Within comment block? */ + else if (is_comment == COMMENT_BLOCK && ch == '*' && next_ch == '/') { + if (debug > 1) { + (void) fprintf(stderr, "~~NO_COMMENT\n"); + } + is_comment = NO_COMMENT; + } + + /* Start of comment to end of line? */ + else if (is_comment == NO_COMMENT && ch == '/' && next_ch == '/') { + if (debug > 1) { + (void) fprintf(stderr, "~~COMMENT_EOL\n"); + } + is_comment = COMMENT_EOL; + + /* Consume next_ch. */ + (void) fputc(ch, stdout); + ch = fgetc(fp); + gross_count++; + net_count++; + } + + /* Start of comment block? */ + else if (is_comment == NO_COMMENT && ch == '/' && next_ch == '*') { + if (debug > 1) { + (void) fprintf(stderr, "~~COMMENT_BLOCK\n"); + } + is_comment = COMMENT_BLOCK; + + /* Consume next_ch. */ + (void) fputc(ch, stdout); + ch = fgetc(fp); + gross_count++; + net_count++; + } + + /* Open single or double quote? */ + else if (is_comment == NO_COMMENT && (ch == '\'' || ch == '"')) { + quote = ch; + } + + (void) fputc(ch, stdout); + +#ifdef DIGRAPHS + /* ISO C11 section 6.4.6 Punctuators, digraphs handled during + * tokenization, but map here and count as 1 byte, like their + * ASCII counter parts. + */ + if (is_comment == NO_COMMENT && quote == 0) { + const char *d; + static const char digraphs[] = "[<:]:>{<%}%>#%:"; + for (d = digraphs; *d != '\0'; d += 3) { + if (ch == d[1] && next_ch == d[2]) { + (void) fputc(next_ch, stdout); + (void) fgetc(fp); + gross_count++; + ch = d[0]; + break; + } + } + } +#endif + /* Sanity check against file size and wc(1) byte count. */ + gross_count++; + + /* End of possible keyword? Care with #word as there can + * be whitespace or comments between # and word. + */ + if ((word[0] != '#' || 1 < wordi) && !isalnum(ch) && ch != '_' && ch != '#') { + if (find_member(cwords, word) != NULL) { + /* Count keyword as 1. */ + net_count = net_count - wordi + 1; + keywords++; + if (debug > 1) { + (void) fprintf(stderr, "~~keyword %zu \"%s\"\n", keywords, word); + } + } + word[wordi = 0] = '\0'; + } + + /* Ignore all whitespace. */ + if (isspace(ch)) { + if (debug > 2) { + (void) fprintf(stderr, "~~ignore whitespace %#02x\n", ch); + } + continue; + } + + /* Ignore begin/end block and end of statement. */ + if (strchr("{;}", ch) != NULL && (isspace(next_ch) || next_ch == EOF)) { + if (debug > 2) { + (void) fprintf(stderr, "~~ignore %c\n", ch); + } + continue; + } + + /* Collect next word not in a string or comment. */ + if (quote == is_comment && (isalnum(ch) || ch == '_' || ch == '#')) { + if (sizeof (word) <= wordi) { + wordi = 0; + } + word[wordi++] = (char) ch; + word[wordi] = '\0'; + } + + net_count++; + } + + /* + * The original author was not entirely in agreement with printing + * these warnings, since he believes that its the programmer's job to + * be cognisant of the rules, guidelines, and the state of their work. + * + * The IOCCC judges observe that enough IOCCC submitters are not so + * cognizant (cognisant) and so make these warnings manditory in the + * hopes it will reduce the number of entries that violate the IOCCC + * size rules. + */ + if (debug == 0) { + if (MAX_SIZE < gross_count) { + (void) fprintf(stderr, "warning: size %zu exceeds Rule 2a %u\n", gross_count, MAX_SIZE); + } + if (MAX_COUNT < net_count) { + (void) fprintf(stderr, "warning: count %zu exceeds Rule 2b %u\n", net_count, MAX_COUNT); + } + } + + (void) fprintf(stderr, out_fmt, net_count, gross_count, keywords); +} + +int +main(int argc, char **argv) +{ + int ch; + + while ((ch = getopt(argc, argv, "6ihv")) != -1) { + switch (ch) { + case 'i': /* ignored for backward compatibility */ + break; + + case 'v': + debug++; + out_fmt = "%lu %lu %lu\n"; + break; + + case '6': /* You're a RTFS master! Congrats. */ + errx(6, "There is NO... Rule 6!\nI'm not a number!\nI'm a free(void *man)!\n"); + + case 'h': + default: + errx(2, "%s", usage); + } + } + + (void) setvbuf(stdin, NULL, _IOLBF, 0); + + /* The Count - 1 Muha .. 2 Muhaha .. 3 Muhahaha ... */ + rule_count(stdin); + + /* + * All Done!!! All Done!!! -- Jessica Noll, age 2 + */ + return 0; +} diff --git a/ioccc/2020/iocccsize.mk b/ioccc/2020/iocccsize.mk new file mode 100644 index 0000000000000000000000000000000000000000..742f2fca346478b3e0613476283e209f311ccbcf --- /dev/null +++ b/ioccc/2020/iocccsize.mk @@ -0,0 +1,61 @@ +#!/usr/bin/env make +# +# iocccsize - IOCCC Source Size Tool +# +# This IOCCC size tool source file is version 2019-06-20-v27. +# +# "You are not expected to understand this" :-) +# +# Public Domain 1992, 2015, 2018, 2019 by Anthony Howe. All rights released. +# With IOCCC minor mods in 2019 by chongo (Landon Curt Noll) ^oo^ + +.POSIX : + +O := .o +E := + +.SUFFIXES : +.SUFFIXES : .c .h .i $O $E + +######################################################################## +### No further configuration beyond this point. +######################################################################## + +top_srcdir := .. +PROJ := iocccsize +TAR_I := -T +CFLAGS := -g -std=c11 -Wall -Wextra -Wno-char-subscripts -pedantic +CFLAGS89 := -g -std=c89 -Wall -Wextra -Wno-char-subscripts -pedantic +CPPFLAGS := +LIBS := + +.c.i: + ${CC} -E ${CFLAGS} ${CPPFLAGS} $*.c >$*.i + +.c$E: + ${CC} ${CFLAGS} ${CPPFLAGS} -o$*$E $*.c + +####################################################################### + +all: build + @true + +build: ${PROJ} + +clean: + -rm -f ${PROJ}.i ${PROJ}$O *.stackdump *.core + +clobber: distclean + +distclean: clean + -rm -fr ${PROJ}$E test a.out + -rm -fr decom a.out iocccsize.dSYM + +test: ./${PROJ}-test.sh ${PROJ} + ./${PROJ}-test.sh -v + +unittest: test + ./${PROJ}-test.sh -v + +version: + git describe --tags --abbrev=0 >VERSION diff --git a/ioccc/2020/kurdyukov1/Makefile b/ioccc/2020/kurdyukov1/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..cdb147106112065451b366afe26cf1a8bf6bb4e3 --- /dev/null +++ b/ioccc/2020/kurdyukov1/Makefile @@ -0,0 +1,585 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-comma -Wno-shorten-64-to-32 -Wno-sign-conversion -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +CSTD= -std=c11 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o +DATA= prog.x86.asm prog.x86_64.asm +TARGET= prog +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/kurdyukov1/compile_commands.json b/ioccc/2020/kurdyukov1/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..6db508db2a39e4f1ed91f37be41e37b758dd7888 --- /dev/null +++ b/ioccc/2020/kurdyukov1/compile_commands.json @@ -0,0 +1,18 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/kurdyukov1/hint.text b/ioccc/2020/kurdyukov1/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..db9dae87ade95f8bcfbc2abb392aebcc05499c23 --- /dev/null +++ b/ioccc/2020/kurdyukov1/hint.text @@ -0,0 +1,71 @@ +# Best utility + +Ilya Kurdyukov +<https://github.com/ilyakurdyukov> +Twitter: @ilyakurdyukov + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog + +### Try: + + # Obfuscated IOCCC + echo IOCCC | ./prog + + ./prog < prog.x86.asm + + ./prog < prog.x86_64.asm + +### Selected Judges Remarks: + +This hash of a C code makes a hash out of input. +Do you understand how? +You should get a-round-to-it figuring it out! + +## Author's comments: +### MD5 with integers + +Just a tiny MD5 checksum utility. Prints hash string of data from stdin. +Work same as `(openssl md5 | cut -d' ' -f2)` command. + +### My objectives + +1. reduce code size as much as possible +2. avoid warnings from GCC/CLANG `-Wall -Wextra -pedantic` +3. portable (regardless of register size and endianness) +4. fit code in a round shape +5. no macro defines +6. no floating-point arithmetics + +### Notes + +The main difficulty of making MD5 code smaller is a 64x4 bytes long table with constants. Which will take more than 512 bytes in text hex encoding. This table is a results of a sine function, so can be generated dynamically, but merging floating-point arithmetics with precise integer calculations is not a great idea, because can make portability issues. + +Attempts to satisfy CLANG `-Weverything` will ruin comma magic, that is so great for obfuscation, so I don't want to care about that. + +Probably, should work correctly on any machines, but I have nothing exotic (like BE or not 32/64) to try it. + +Added a macro hack to make stdin work in binary mode under Windows (tested under mingw64), otherwise the hashes can be incorrect. + +### Bonus + +- `prog.extra.c` the same with the sine function (so smaller), and in different shapes. + +- `prog.x86_64.asm` contains same program, but written on assembly for x86_64 Linux, for the sake of less executable size. Which is 500 bytes long (where 120 is for ELF headers) after compilation. Algorithm details is slightly differ (like constants packing), just to make smaller binary code. It's interesting to compare density of binary code and obfuscated C. + +- `prog.x86.asm` and for x86, although the headers are smaller, but the binary code is larger due to fewer registers and lack of 64-bit multiply. + + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/kurdyukov1/prog.c b/ioccc/2020/kurdyukov1/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..f4f3917efa6a54081d1a6ef8d0b2266e786ffd12 --- /dev/null +++ b/ioccc/2020/kurdyukov1/prog.c @@ -0,0 +1,31 @@ +#include <stdint.h> +#include <stdio.h> +#ifdef _WIN32 +#include <io.h> +#include <fcntl.h> +#define main() M();i\ +nt main(){setmode(fi\ +leno(stdin),O_BINARY\ +);return M();}int M() +#endif + + int main() + {uint32_t h[20]={0}, + i=0,x=~i/15,f=x*x-x,a=f^x, + b=f^x*9,c=~a,d=~b;int64_t z=0, + g=0,l=566548,p=585873,o=882346,e + ,m=64336,k,n;for(;d=h[c=h[b=h[a=h[i= + 0]+=a,1]+=b,2]+=c,3]+=d,f;){for(n=64 + ;n==8?h[h[5]=g,4]=g>>32,f=z>=0:n;)h[4+ + --n/4]=x=(z<0?0:(z=getchar())>=0?g+=8,z: + 128)<<24|x>>8;;for(e=0,k=~e<<40;(x=i/16) + <4;a=d,d=c,c=b,b+=x<<n|x>>(32-n))n=((e*m + +k*p)>>21)+e*l+k*o,k=(((k*m-e*p)>>21)+k* + l-e*o)>>20,e=n>>20,n=(i|12)*152%543%82 + %4+i%4*43/8+4,x=a+((x>2?~d|b:x>1?b^d + :x?(b^c)&d:(c^d)&~b)^c)+h[19-((x*7/2 + &5)-~(x*5&6)*i++)%16]+(e>>40^e>> + 8);}for(;i<33;putchar(i++<32?a + +=a>9?'a'-10:'0':'\n'))a=h + [i/8]>>(i%8*4^4)&15; + return 0;} diff --git a/ioccc/2020/kurdyukov1/prog.extra.c b/ioccc/2020/kurdyukov1/prog.extra.c new file mode 100644 index 0000000000000000000000000000000000000000..917de49abc971f571d18046885874655f1b0ed60 --- /dev/null +++ b/ioccc/2020/kurdyukov1/prog.extra.c @@ -0,0 +1,80 @@ +#include <stdint.h> +#include <stdio.h> +#include <math.h> +#ifdef _WIN32 +#include <io.h> +#include <fcntl.h> +#define main() M();i\ +nt main(){setmode(fi\ +leno(stdin),O_BINARY\ +);return M();}int M() +#endif + +#ifndef IDX +#define IDX 1 +#endif +#if IDX==1 // float round + + int main(){ + uint32_t i=0,h[20]= + {0},x=~i/15,f=x*x-x,a=f^x + ,b=f^x*9,c=~a,d=~b;int64_t z= + 0,g=0,n;for(;d=h[c=h[b=h[a=h[n= + i=0]+=a,1]+=b,2]+=c,3]+=d,f;){for(; + n==56?h[h[18]=g,19]=g>>32,f=z>=0:n< + 64;)h[n++/4+4]=x=(z<0?0:(z=getchar()) + >=0?g+=8,z:128)<<24|x>>8;;for(;(x=i>> + 4)<4;a=d,d=c,c=b,b+=x<<n|x>>(32-n))n= + (i|12)*152%543%82%4+i%4*43/8+4,x=a+(( + x>2?~d|b:x>1?b^d:x?(b^c)&d:(c^d)&~b + )^c)+h[((x*7/2&5)-~(x*5&6)*i++)%16+ + 4],x+=a=fabs(sin(i))*8*(8<<26); + }for(;n<33;putchar(n++<32?a+= + a>9?'a'-10:'0':'\n'))a=h[ + n/8]>>(n%8*4^4)&15; + ;return 0;} + +#elif IDX==2 // float square + +int main(){uint32_t f=0,x=~f/15, +i=x*x-x,a=i^x,b=i^x*9,n,c=~a,d=~ +b,h[20]={0};int64_t z=0,g=0;for( +;d=h[c=h[b=h[a=h[i=0]+=a,1]+=b,2 +]+=c,3]+=d,!f;){for(f=64;f==8?h[ +h[5]=g,4]=g>>32,z>=0:f;)h[--f/4+ +4]=x=x>>8|(z<0?0:(z=getchar())>= +0?g+=8,z:128)<<24;for(;(x=i/16)< +4;a=d,d=c,c=b,b+=x<<n|x>>(32-n)) +n=(i|12)*152%543%82%4+i%4*43/8+4 +,x=a+((x>2?~d|b:x>1?b^d:x?(b^c)& +d:(c^d)&~b)^c)+h[19-((x*7/2&5)-~ +(x*5&6)*i++)%16],x+=a=fabs(sin(i +))*8*(8<<26);}for(;i<33;putchar( +i++<32?a+=a>9?'a'-10:'0':'\n'))a +=h[i/8]>>(i%8*4^4)&15;return 0;} + +#elif IDX==3 // integer 62x10, twitter profile cover (3:1) + +int main(){uint32_t i=0,x=~i/15,f=x*x-x,a=f^x,b=f^x*9,c=~a,d=~ +b,h[20]={0};int64_t e,k,l=566548,m=64336,o=882346,p=585873,n,z +=0,g=0;for(;d=h[c=h[b=h[a=h[e=i=n=0]+=a,1]+=b,2]+=c,3]+=d,f;){ +for(;n==56?h[h[18]=g,19]=g>>32,f=z>=0:n<64;)h[n++/4+4]=x=x>>8| +(z<0?0:(z=getchar())>=0?g+=8,z:128)<<24;;for(k=~e<<40;(x=i/16) +<4;a=d,d=c,c=b,b+=x<<n|x>>(32-n))n=((e*m+k*p)>>21)+e*l+k*o,k=( +((k*m-e*p)>>21)+k*l-e*o)>>20,e=n>>20,n=(i|12)*152%543%82%4+i%4 +*43/8+4,x=a+((x?x>2?~d|b:x>1?b^d:(b^c)&d:(c^d)&~b)^c)+h[((x*7/ +2&5)+(x*5%8|1)*i++)%16+4]+(e>>8^e>>40);}for(;n<33;putchar(n++< +32?a+=a<10?'0':'a'-10:'\n'))a=h[n/8]>>(n%8*4^4)&15;;return 0;} + +#elif IDX==4 // float 65x8, linkedin profile cover (4:1) + +int main(){uint32_t i=0,x=~i/15,f=x*x-x,a=f^x,b=f^x*9,n,c=~a,d=~b +,h[20]={0};int64_t z=0,g=0;for(;d=h[c=h[b=h[a=h[n=i=0]+=a,1]+=b,2 +]+=c,3]+=d,f;){for(;n==56?h[h[18]=g,19]=g>>32,f=z>=0:n<64;)h[n++/ +4+4]=x=x>>8|(z<0?0:(z=getchar())>=0?g+=8,z:128)<<24;for(;(x=i/16) +<4;x+=a=fabs(sin(i))*8*(8<<26),a=d,d=c,c=b,b+=x<<n|x>>(32-n))n=(i +|12)*152%543%82%4+i%4*43/8+4,x=a+(x?(x>2?~d|b:x>1?b^d:(b^c)&d)^c: +((c^d)&b)^d)+h[((x*7/2&5)+(x*5%8|1)*i++)%16+4];}for(;n<33;putchar +(n++<32?a+=a>9?'a'-10:'0':'\n'))a=h[n/8]>>(n%8*4^4)&15;return 0;} + +#endif diff --git a/ioccc/2020/kurdyukov1/prog.orig.c b/ioccc/2020/kurdyukov1/prog.orig.c new file mode 100644 index 0000000000000000000000000000000000000000..23adfa5114b0e1880652aac04ea473b2ab22f730 --- /dev/null +++ b/ioccc/2020/kurdyukov1/prog.orig.c @@ -0,0 +1,24 @@ +#include <stdint.h> +#include <stdio.h> + + int main(){ + uint32_t f=0,i,n=0, + a=1732584193,b=4023233417 + ,q=32,c=~a,d=~b,x,h[]={x=a,b, + c,d,80200,745,108189,38200},s[16] + ;int64_t z=0,g=0,l=566548,m=64336,o + =882346,p=585873,e,k,y;for(;!f;)if(s[ + n++/4]=x=x>>8|(z<0?0:(z=getchar())>=0?g + +=8,z:128)<<24,n==56?s[s[14]=g,15]=g>>q + ,f=z<0:n/64){for(e=i=0,k=~e<<40;i<64;i++, + a=d,d=c,c=b,b+=x<<n|x>>(q-n))y=((e*m+k*p) + >>21)+e*l+k*o,k=(((k*m-e*p)>>21)+k*l-e*o) + >>20,e=y>>20,x=i/16+4,n=h[x],x=a+(x>4?( + x>6?~d|b:x>5?b^d:(b^c)&d)^c:((c^d)&b)^d + )+s[(n/8%8*i+n%8)&15]+(e>>8^e>>40),n= + (n>>(i%4*3+6)&7)+i%4*6+2;d=h[c=h[b= + h[a=h[n=0]+=a,1]+=b,2]+=c,3]+=d;} + for(;n<33;)a=h[n/8]>>(n%8*4^4 + )&15,putchar(++n>q?'\n':a + +(a<10?'0':'a'-10)) + ;return 0;} diff --git a/ioccc/2020/kurdyukov1/prog.x86.asm b/ioccc/2020/kurdyukov1/prog.x86.asm new file mode 100644 index 0000000000000000000000000000000000000000..798b434684f93bbe4f613116e846a9316eea59cf --- /dev/null +++ b/ioccc/2020/kurdyukov1/prog.x86.asm @@ -0,0 +1,276 @@ +; -*- tab-width: 8 -*- + +; MD5 checksum utility for x86 Linux, assembly version +; To build: nasm -f bin -O9 prog.x86.asm -o prog + +%define @pie 0 + +BITS 32 +%if @pie +ORG 0 +%else +ORG 0x400000 +%endif + +%define @sys_exit 1 +%define @sys_read 3 +%define @sys_write 4 + +section .text + +_code_seg: +_elf: db 7Fh,'ELF',1,1,1,0 ; e_ident + dq 0 + dw 2+@pie ; e_type + dw 3 ; e_machine + dd 1 ; e_version + dd _start ; e_entry + dd .ph-_elf ; e_phoff + dd 0 ; e_shoff + dd 0 ; e_flags + dw 0x34 ; e_ehsize + dw 0x20,1 ; e_phentsize, e_phnum + dw 0x28,0 ; e_shentsize, e_shnum + dw 0 ; e_shstrndx +.ph: dd 1 ; p_type + dd 0 ; p_offset + dd _code_seg ; p_vaddr + dd _code_seg ; p_paddr + dd _code_end-_code_seg ; p_filesz + dd _code_end-_code_seg ; p_memsz + dd 5, 0x1000 ; p_flags, p_align + +_start: + +%define @cos_hi 1133096 ; l +%define @cos_lo 128673 ; m +%define @sin_hi 1764692 ; o +%define @sin_lo 1171746 ; p + + sub esp, 64*4 + push @cos_hi + push @sin_hi + push @cos_lo + push @sin_lo + xor ebx, ebx + push -1 << (40 - 32) + push ebx + push ebx + push ebx +.4x: xor ebp, ebp + xor edi, edi +.4: mov eax, ebx + mov esi, ebx + and eax, 7 + and esi, 3 + add eax, esi + mov ecx, [esp+16+eax*2] + and esi, 1 + mov eax, [esp+esi*8] + mul ecx + imul ecx, [esp+esi*8+4] + add edx, ecx + test bl, 1+4 + jne .4a + sub edi, eax + sbb ebp, edx + jmp .4b +.4a: add edi, eax + adc ebp, edx +.4b: inc ebx + test bl, 1 + jne .4 + shrd edi, ebp, 21 + sar ebp, 21 + test bl, 2 + jne .4 + pop eax + pop edx + pop ecx + pop esi + push ebp + push edi + test bl, 4 + je .4d + push edx + push eax + push esi + push ecx + jmp .4x + +.4d: mov ecx, ebx + shrd edi, ebp, 8 + sar ebp, 31 + shr ecx, 3 + xor edi, ebp + cmp ecx, 64+1 + mov [esp+32+ecx*4-4], edi + jne .4x + add esp, 32 + + mov eax, ~0xefcdab89 + cdq + push edx + push edx + mov ecx, ~0x67452301 + push eax + push ecx + not eax + not ecx + push eax + push ecx + sub esp, 64+4 + +.2: mov edi, esp + xor eax, eax + lea ecx, [eax+16] + cld + rep stosd + test edx, edx + lea edx, [eax+64] + xchg ebx, eax ; 0 (stdin) + jne .2a + mov ecx, esp +%if @sys_read != @sys_write-1 + lea edi, [ebx+@sys_read] +%endif + call _io + mov byte [ecx], 0x80 + sub ecx, esp + shl ecx, 3 +.2a: mov edi, esp + lea esi, [edi+64+4+16] + add [esi], ecx + adc [esi+4], ebx + cmp edx, 8 + jb .2b + neg edx + add edi, 56 + movsd + movsd +.2b: push edx + xor ebx, ebx + + mov edx, esp + mov ecx, [edx+0x40+8] + mov edi, [edx+0x44+8] + mov esi, [edx+0x48+8] + mov ebp, [edx+0x4c+8] +.1: add ecx, [esp+64+16+16+ebx*4] + + ; ecx, edi, esi, ebp + +%define PACK(a,b,c,d,e,f) (d<<15|c<<10|b<<5|a)<<4|e<<24|f + + mov edx, ebx + shr edx, 5 + mov eax, ebp + jne .1b + jc .1a + ; 0: ((b^c)&a)^c + mov edx, PACK(7,12,17,22,1,0) + xor eax, esi + and eax, edi + xor eax, ebp + jmp .1e + +.1a: ; 1: ((a^b)&c)^b + mov edx, PACK(5, 9,14,20,5,1) + mov eax, edi + xor eax, esi + and eax, ebp + jmp .1d + +.1b: jc .1c + ; 2: a^b^c + mov edx, PACK(4,11,16,23,3,5) + xor eax, edi + jmp .1d + +.1c: ; 3: (~c|a)^b + mov edx, PACK(6,10,15,21,7,0) + not eax + or eax, edi +.1d: xor eax, esi +.1e: add eax, ecx + + mov ecx, edx + shr ecx, 24 + imul ecx, ebx + add ecx, edx + and ecx, 15 + add eax, [esp+4+ecx*4] + + mov ecx, ebx + and ecx, 3 + lea ecx, [ecx+ecx*4+4] + shr edx, cl + mov ecx, edx + rol eax, cl + + mov ecx, ebp ; a = d + mov ebp, esi ; d = c + mov esi, edi ; c = b + add edi, eax ; b += x + inc ebx + cmp ebx, 64 + jne .1 + + mov edx, esp + add [edx+0x40+8], ecx + add [edx+0x44+8], edi + add [edx+0x48+8], esi + add [edx+0x4c+8], ebp + pop edx + test edx, edx + jge .2 + + xor edx, edx + mov edi, esp +.3: mov eax, edx + shr eax, 1 + mov al, [esp+64+4+eax] + jc .3a + shr al, 4 +.3a: and al, 15 + cmp al, 10 + jb .3b + add al, 'a'-'0'-10 +.3b: add al, '0' + stosb + inc edx + cmp edx, 32 + jne .3 + mov al, 10 + stosb + inc edx + + mov ecx, esp + lea ebx, [edx-32] ; 1 (stdout) +%if @sys_read != @sys_write-1 + lea edi, [ebx+@sys_write-1] +%endif + call _io + xor ebx, ebx ; exit code + lea eax, [ebx+@sys_exit] + int 0x80 + +_io: +%if @sys_read != @sys_write-1 + mov eax, edi +%else + lea eax, [ebx+@sys_read] +%endif + push edx + int 0x80 + pop edx + test eax, eax + jle .1 + add ecx, eax + sub edx, eax + ja _io + cdq +.1: ret + +_code_end: + diff --git a/ioccc/2020/kurdyukov1/prog.x86_64.asm b/ioccc/2020/kurdyukov1/prog.x86_64.asm new file mode 100644 index 0000000000000000000000000000000000000000..b00bbf939f8419f4a308ea61d9ad83e1de0ff9e2 --- /dev/null +++ b/ioccc/2020/kurdyukov1/prog.x86_64.asm @@ -0,0 +1,224 @@ +; -*- tab-width: 8 -*- + +; MD5 checksum utility for x86_64 Linux, assembly version +; To build: nasm -f bin -O9 prog.x86_64.asm -o prog + +%define @pie 0 + +BITS 64 +%if @pie +ORG 0 +%else +ORG 0x400000 +%endif + +%define @sys_read 0 +%define @sys_write 1 +%define @sys_exit 60 + +section .text + +_code_seg: +_elf: db 0x7f,'ELF',2,1,1,0 ; e_ident + dq 0 + dw 2+@pie ; e_type + dw 62 ; e_machine + dd 1 ; e_version + dq _start ; e_entry + dq .ph-_elf ; e_phoff + dq 0 ; e_shoff + dd 0 ; e_flags + dw 0x40 ; e_ehsize + dw 0x38, 1 ; e_phentsize, e_phnum + dw 0x40, 0 ; e_shentsize, e_shnum + dw 0 ; e_shstrndx +.ph: dd 1, 5 ; p_type, p_flags + dq 0 ; p_offset + dq _code_seg ; p_vaddr + dq _code_seg ; p_paddr + dq _code_end-_code_seg ; p_filesz + dq _code_end-_code_seg ; p_memsz + dq 0x1000 ; p_align + +_start: + mov rax, ~0xefcdab8967452301 + push rax + not rax + push rax + sub rsp, 64+8 + + xor r12, r12 +; xor edx, edx + cdq + +.2: mov rdi, rsp + xor eax, eax + lea ecx, [rax+8] + rep stosq + test edx, edx + lea edx, [rax+64] + jne .2a + xchg edi, eax ; 0 (stdin) + mov rsi, rsp +%if @sys_read != 0 || @sys_write != 1 + lea ebx, [rdi+@sys_read] +%endif + call _io + mov byte [rsi], 0x80 + sub esi, esp + lea r12, [r12+rsi*8] +.2a: cmp edx, 8 + jb .2b + neg edx + mov [rsp+56], r12 +.2b: push rdx + xor ebx, ebx + mov r14, 0x8a51407da834 << 15 ; cos(1) * 2^48 + mov r15, 0xd76aa4784867 << 15 ; sin(1) * 2^48 + mov r8, r14 + mov r9, r15 + + mov rdx, rsp + mov ecx, [rdx+0x50] + mov edi, [rdx+0x54] + mov esi, [rdx+0x58] + mov ebp, [rdx+0x5c] +.1: + mov rax, r9 + cqo + shr rax, 31 + xor eax, edx + add ecx, eax + + ; r9' = r9 * r14 + r8 * r15 + ; r8' = r8 * r14 - r9 * r15 + + mov rax, r9 + imul r15 + mov r11, rdx + mov rax, r8 + imul r14 + sub rdx, r11 + lea rax, [rdx+rdx] + xchg rax, r8 + imul r15 + lea rax, [rdx+rdx] + xchg rax, r9 + imul r14 + lea r9, [rdx*2+r9] + + ; r10d, edi, esi, ebp + +%define PACK(a,b,c,d,e,f) (d<<15|c<<10|b<<5|a)<<4|e<<24|f + + mov edx, ebx + shr edx, 5 + mov eax, ebp + jne .1b + jc .1a + ; 0: ((b^c)&a)^c + mov edx, PACK(7,12,17,22,1,0) + xor eax, esi + and eax, edi + xor eax, ebp + jmp .1e + +.1a: ; 1: ((a^b)&c)^b + mov edx, PACK(5, 9,14,20,5,1) + mov eax, edi + xor eax, esi + and eax, ebp + jmp .1d + +.1b: jc .1c + ; 2: a^b^c + mov edx, PACK(4,11,16,23,3,5) + xor eax, edi + jmp .1d + +.1c: ; 3: (~c|a)^b + mov edx, PACK(6,10,15,21,7,0) + not eax + or eax, edi +.1d: xor eax, esi +.1e: add eax, ecx + + mov ecx, edx + shr ecx, 24 + imul ecx, ebx + add ecx, edx + and ecx, 15 + add eax, [rsp+8+rcx*4] + + mov ecx, ebx + and ecx, 3 + lea ecx, [rcx+rcx*4+4] + shr edx, cl + mov ecx, edx + rol eax, cl + + mov ecx, ebp ; a = d + mov ebp, esi ; d = c + mov esi, edi ; c = b + add edi, eax ; b += x + inc ebx + cmp ebx, 64 + jne .1 + + mov rdx, rsp + add [rdx+0x50], ecx + add [rdx+0x54], edi + add [rdx+0x58], esi + add [rdx+0x5c], ebp + pop rdx + test edx, edx + jge .2 + + xor edx, edx + mov rdi, rsp +.3: mov eax, edx + shr eax, 1 + mov al, [rsp+0x40+8+rax] + jc .3a + shr al, 4 +.3a: and al, 15 + cmp al, 10 + jb .3b + add al, 'a'-'0'-10 +.3b: add al, '0' + stosb + inc edx + cmp edx, 32 + jne .3 + mov al, 10 + stosb + inc edx + + mov rsi, rsp + lea edi, [rdx-32] ; 1 (stdout) +%if @sys_read != 0 || @sys_write != 1 + lea ebx, [rdi+@sys_write-1] +%endif + call _io + xor edi, edi ; exit code + lea eax, [rdi+@sys_exit] + syscall + +_io: +%if @sys_read != 0 || @sys_write != 1 + mov eax, ebx +%else + mov eax, edi +%endif + syscall + test eax, eax + jle .1 + add rsi, rax + sub edx, eax + ja _io +; xor edx, edx + cdq +.1: ret + +_code_end: + diff --git a/ioccc/2020/kurdyukov2/Makefile b/ioccc/2020/kurdyukov2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3e61a7ebfea444e326dcbf665160d8b2984cb512 --- /dev/null +++ b/ioccc/2020/kurdyukov2/Makefile @@ -0,0 +1,595 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-comma -Wno-implicit-int-conversion -Wno-padded -Wno-shadow \ + -Wno-shorten-64-to-32 -Wno-sign-conversion -Wno-missing-field-initializers \ + -Wno-conversion -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +CSTD= -std=c11 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} +LIBJPEG= -ljpeg +LIBPNG= -lpng + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o prog_png.o prog_ppm.o +DATA= sample.jpg +TARGET= prog prog_png prog_ppm +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} ${LIBJPEG} + +prog_png: prog.png.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} ${LIBPNG} + +prog_ppm: prog.ppm.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/kurdyukov2/compile_commands.json b/ioccc/2020/kurdyukov2/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..6db508db2a39e4f1ed91f37be41e37b758dd7888 --- /dev/null +++ b/ioccc/2020/kurdyukov2/compile_commands.json @@ -0,0 +1,18 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/kurdyukov2/hint.text b/ioccc/2020/kurdyukov2/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..3e54b5a6a3c25aeaba5b24c1511cb45007586556 --- /dev/null +++ b/ioccc/2020/kurdyukov2/hint.text @@ -0,0 +1,99 @@ +# Least detailed + +Ilya Kurdyukov +<https://github.com/ilyakurdyukov> +Twitter: @ilyakurdyukov + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make prog prog_png prog_ppm + ./prog Nrect infile outfile + +### Try: + + # Take a selfie + ./prog 1000 selfie.jpg output.jpg + # Admire your portrait in cubist style + + (echo P6 1024 1024 255; dd if=/dev/urandom bs=3M count=1) > random.ppm + # Look at random.ppm. Do you see any patterns? + ./prog_ppm 1000 random.ppm output.ppm + # See which patterns the program has found + + for i in 0001 0002 0004 0008 0016 0032 0064 0128 0256 0512 1024 2048 4096 8192 ; do ./prog $i sample.jpg out$i.jpg; done + # Then flip through the out*.jpg pictures and see when you start recognizing the image. + +### Selected Judges Remarks: + +This entry has reminded us of a winning entry back in the early 90s. Can you guess which one? + +For a given image, try graphing the execution time relative to the number of rectangles. +What is the complexity? Is it obvious from the source code? + +## Author's comments: +### Usage + +This program divides the image into a specified number of rectangles. This process is content aware, so algorithm tries to match most of the information. However, it doesn't finds the best theoretically possible layout. + + ./prog 1000 input.jpg output.jpg + +### Building + +You can build three versions, depending on the image format. + +Default is JPEG version, if you have the *libjpeg* development package installed in your system, then `make` without arguments should do the thing. + +If you want to use *libjpeg* compiled from sources, then use `LIBS` define to specify the path to includes and the library. + + make prog LIBJPEG="-Ijpeg-6b jpeg-6b/libjpeg.a" + +Use this command to build a PNG version (you need *libpng*): + + make prog_png LIBPNG="-lpng" + +And the PPM version (no additional dependencies, can read raw/ASCII PPM, writes raw PPM): + + make prog_ppm + +### Building on OSX + +- Thanks to Cody Ferguson for this information! + +First, make sure you have the compiler tools installed e.g. by: + + $ sudo xcode-select --install + +Make sure you install [MacPorts](https://www.macports.org/install.php). Then do: + + $ sudo port install jpeg libpng ImageMagick + +The program itself doesn't need ImageMagick, install it only if you plan to make gifs from the results using "makegif.sh". + +After that’s installed you need to run make with these options: + + $ make LIBS="-I/opt/local/include -L/opt/local/lib" + +### Notes + +Made this thing while experimenting with the idea of representing an image with rectangles (lossy compression). It's not very good in that sense, but the results look funny, like a kind of cubism pixelart. + +Do not use values above 50000, it gonna be slow. + +To understand how this works, just try running with 1,2,3,4... number of rectangles. At each iteration, the rectangle with the biggest difference from the picture data is split (halves may have different size) horizontally or vertically to get the minimum difference. + +You can use this command to make a gif from output images (uses ImageMagick): +`convert -delay 10 -dither none -loop 0 $(ls out*.png | sort -V) $(ls out*.png | sort -rV) +map out.gif` +Also provided `makegif.sh` to aid with gif creation. + + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/kurdyukov2/makegif.sh b/ioccc/2020/kurdyukov2/makegif.sh new file mode 100755 index 0000000000000000000000000000000000000000..2fd63a145a29396ac24d46b5b6a1ac1e716e2b26 --- /dev/null +++ b/ioccc/2020/kurdyukov2/makegif.sh @@ -0,0 +1,31 @@ +#!/bin/bash +image=${1:-"input.jpg"} +output=${2:-"output.gif"} +prog=${3:-"./prog"} +ext="${image##*.}" +dir="gif" +[ $# -lt 3 ] && [ "$ext" = "png" -o "$ext" = "ppm" ] && prog="./prog_$ext" +[ -f "$image" ] || { + echo "Usage: makegif.sh image.jpg output.gif ./prog" + echo "Depends: ImageMagick, bc (basic calculator)" + echo "Note: don't use large images (dimensions above 1000), ImageMagick may fail." + echo "Uses \"gif\" directory for temporary files." + exit 1 +} +mkdir -p "$dir" +i=8 ; x=$i ; j=0 +while [ $x -le 16000 ]; do + x="$(echo "a=$i*e(l(2)/4*$j)+0.5;scale=0;a/1" | bc -l)" + echo "### $j : $x" + list[j]="$dir/out$j.$ext" + "$prog" "$x" "$image" "$dir/out$j.$ext" ; j=$((j+1)) +done +i=$j ; j=$((j-2)) +while [ $j -ge 1 ]; do +### Uncomment the following line if you want to make a GIF in an image editor such as GIMP +# cp "$dir/out$j.$ext" "$dir/out$i.$ext" + list[i]="$dir/out$j.$ext" + i=$((i+1)) ; j=$((j-1)) +done +convert -delay 10 -dither none -loop 0 "${list[@]}" +map "$output" + diff --git a/ioccc/2020/kurdyukov2/prog.c b/ioccc/2020/kurdyukov2/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..17ed775be040653f3d8650c6a03889e945478714 --- /dev/null +++ b/ioccc/2020/kurdyukov2/prog.c @@ -0,0 +1,32 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include "jpeglib.h" +#define J(x) jpeg_##x; +#define A B(p=t+Z*b+y*S;l=w*h;for(u=j=0;l&&j<b;p++)X->c[j\ +++]=(p[w*b+h*S]-p[w*b]-p[h*S]+*p+l/2)/l,-),u+=z*z; X->d=u;} +#define G(h,n) D.comp_info[0].h##_samp_factor=1;D.image_##n; +#define B(e,f) {int x,Z=X->x,y=X->y,w=X->w,h=X->h;e;for(;h--\ +;y++)for(x=Z;x<w+Z;x++)for(j=0;j<b;j++)z=d[y*s+x*b+j]f X->c[j] +#define H(W,H,w,h,B,i) for(B=z=i=0;++z<w;u>B?B=u,i=z:0)for(u=j\ +=0;p=t+x*b+y*S+j,j<b;j++)K=p[z*W+h*H]-p[z*W],Q=N->c[j]*h,L=p[w*\ +W+h*H]-p[w*W]-K-Q*(w-z),K-=p[h*H]-*p+Q*z,u+=L<0?-L:L,u+=K<0?-K:K; +#define W(r,X,a,o,Y,b,c,S) {S J(error_mgr E)S J(c##_##S D);D.err=\ +J(std_error(&E))if(!(F=fopen(*++V,#r)))break;J(create_##c(I=&D))J(\ +stdio_##o(I,F))Y;J(start_##c X)while((y=D.a##_scanline)<h)R=d+y*s,J\ +(b##_scanlines(I,O=&R,1))J(finish_##c(I))J(destroy_##c(I))fclose(F);} +int main(int c,char**V){while(c==4){intptr_t w,h,s,b,S,j,i,x,y,v,q,z,k +,l,g=JCS_RGB,n=atoi(*++V);uint8_t*d;void*O,*R,*F,*I;int64_t*p,e,f,u,K,L +,*t,Q,U=1;struct{uint16_t x,y,w,h;uint8_t c[4];int64_t d;}*P,*N,*X,o={0} +;W(rb,(I);w=D.output_width;h=D.output_height;b=D.output_components;L=n=n +<1?1:n>w*h?w*h:n;K=S=(s=w*b)+b;K=sizeof(o)*L+(u=K*h+K)*9;if((L=(size_t)K +)-K||!(t=malloc(K)))break;X=P=O=t+u;d=O=P+n,output,src,J(read_header(I,U +))D.do_fancy_upsampling=0;D.out_color_space=g,read,decompress,struct)fo\ +r(i=j=0;j<b;j++)for(x=j-S,z=j-b;x<S*h;x+=b)t[x+S]=x<0?y=0:t[x]+(u=y--?u+ +d[z+=b]:(y=w,0));;o.w=w;o.h=h;*X=o;A for(;N=X=P,U&&++i<n;){for(U=j=0;j++ +<i;X++)U=X->d>U?(N=X)->d:U;;o=*N;v=o.w;q=o.h;x=o.x;y=o.y;H(b,S,v,q,e,k)H +(S,b,q,v,f,l)e<f?o.y+=N->h=l,o.h-=l:(o.x+=N->w=k,o.w-=k);*X=o;A X=N;A}f\ +or(;i--;X++)B(,=);}W(wb,(I,1),next,dest,D.input_components=b;D.in_color\ +_space=g;J(set_defaults(I))G(h,width=w)G(v,height=h)J(set_quality(I,100, +D.optimize_coding=1)),write,compress,struct)free(t);return 0;}return 1;} + diff --git a/ioccc/2020/kurdyukov2/prog.png.c b/ioccc/2020/kurdyukov2/prog.png.c new file mode 100644 index 0000000000000000000000000000000000000000..5e213ae61d48305ce96831756ea4c66cee3e280d --- /dev/null +++ b/ioccc/2020/kurdyukov2/prog.png.c @@ -0,0 +1,32 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <png.h> +#define G(n) png_get_##n(J,I); +#define A B(p=t+Z*b+y*S;l=w*h;for(u=j=0;l&&j<b;p++)X->c[j\ +++]=(p[w*b+h*S]-p[w*b]-p[h*S]+*p+l/2)/l,-),u+=z*z; X->d=u;} +int main(int c,char**V){while(c==4){struct{uint16_t x,y,w,h; +#define B(e,f) {int x,Z=X->x,y=X->y,w=X->w,h=X->h;e;for(;h--\ +;y++)for(x=Z;x<w+Z;x++)for(j=0;j<b;j++)z=d[y*s+x*b+j]f X->c[j] +#define H(W,H,w,h,B,i) for(B=z=i=0;++z<w;u>B?B=u,i=z:0)for(u=j\ +=0;p=t+x*b+y*S+j,j<b;j++)K=p[z*W+h*H]-p[z*W],Q=N->c[j]*h,L=p[w*\ +W+h*H]-p[w*W]-K-Q*(w-z),K-=p[h*H]-*p+Q*z,u+=L<0?-L:L,u+=K<0?-K:K; +#define W(a,b,c,d,e,f,g,h) if(!(F=fopen(*++V,#a)))return 1;b;J=h\ +##create_##g##_struct(PNG_LIBPNG_VER_STRING,0,0,0);I=h##create_i\ +nfo_struct(J);h##init_io(J,F);c;h##g##_info(J,I);d;h##g##_image(\ +J,R);h##g##_end(J,0); O=&J;h##destroy_##g##_struct e;fclose(F);f; +uint8_t c[4];int64_t d;}*P,*N,*X,o;uint8_t**R,*d;intptr_t n=atoi( +*++V),l,h,s,b,S,i,j,x,y,v,q,z,k,w;int64_t*p,e,f,u,K,L,*t,Q,U;void +*O=&K,*J,*I,*Z,*F;W(rb,if(png_sig_cmp(O,0,fread(O,U=1,8,F)))break +,png_set_sig_bytes(J,8),w=G(image_width)h=G(image_height)png_rea\ +d_update_info(J,I);y=8-G(bit_depth)b=G(channels)c=G(color_type)L= +n=n<1?1:n>w*h?w*h:n;K=S=(s=w*b)+b;K=h*sizeof(*R)+sizeof(*X)*L+(u= +K*h+K)*9;if(y||(L=(size_t)K)-K||!(R=malloc(K)))break;t=O=R+h;X=P= +O=t+u;for(d=O=P+n;y<h;y++)R[y]=d+y*s,(O,Z=&I,0);for(X->x=X->y=i=j +=0;j<b;j++)for(x=j-S,z=j-b;x<S*h;x+=b)t[x+S]=x<0?y=0:t[x]+(u=y--? +u+d[z+=b]:(y=w,0)),X->w=w;X->h=h;A for(;N=X=P,U&&++i<n;){for(U=j= +0;j++<i;X++)U=X->d>U?(N=X)->d:U,read,png_)o=*N;v=o.w;q=o.h;x=o.x; +y=o.y;H(b,S,v,q,e,k)H(S,b,q,v,f,l)e<f?o.y+=l,o.h-=N->h=l:(o.x+=k, +o.w-=N->w=k);*X=o;A X=N;A}for(;i--;X++)B(,=);}W(wb,,png_set_IHDR( +J,I,w,h,8,c,0,0,0),,(O,Z),free(R),write,png_)return 0;}return 1;} + diff --git a/ioccc/2020/kurdyukov2/prog.ppm.c b/ioccc/2020/kurdyukov2/prog.ppm.c new file mode 100644 index 0000000000000000000000000000000000000000..e21585e68ff037f852728ac53460583d0356a250 --- /dev/null +++ b/ioccc/2020/kurdyukov2/prog.ppm.c @@ -0,0 +1,27 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#define A B(p=t+Z*b+y*S;l=w*h;for(u=j=0;l&&j<b;p++)X->c[j\ +++]=(p[w*b+h*S]-p[w*b]-p[h*S]+*p+l/2)/l,-),u+=z*z; X->d=u;} +int main(int c,char**V){while(c==4){struct{uint16_t x,y,w,h; +#define B(e,f) {int x,Z=X->x,y=X->y,w=X->w,h=X->h;e;for(;h--\ +;y++)for(x=Z;x<w+Z;x++)for(j=0;j<b;j++)z=d[y*s+x*b+j]f X->c[j] +#define H(W,H,w,h,B,i) for(B=z=i=0;++z<w;u>B?B=u,i=z:0)for(u=j\ +=0;p=t+x*b+y*S+j,j<b;j++)K=p[z*W+h*H]-p[z*W],Q=N->c[j]*h,L=p[w*\ +W+h*H]-p[w*W]-K-Q*(w-z),K-=p[h*H]-*p+Q*z,u+=L<0?-L:L,u+=K<0?-K:K; +#define W(r,X) if(!(F=fopen(*++V,#r)))break;X(d,s,h,F); fclose(F); +#define G(n,x,y){for(k=0,n=-x;!k;k=z-' '&&z-'\n'&&z-'\r'&&z-'\t'&\ +&z-EOF?z<'0'||z>'9'||(n=(n<0?0:n*10)+z-'0')>>15?n=-1:0:n>=0||z>>8\ +)for(;z=fgetc(F),k++?z-'\n'&&z-EOF:z=='#';);if(x?y:n-3&&n-6)break; +uint8_t c[4];int64_t d;}*P,*N,*X,o;void*O,*F;int64_t*p,e,f,u,K,L,* +t,Q,U=1;uint8_t*d;intptr_t n=atoi(*++V),w,h,s,b=3,S,i=0,j,x=0,y,v, +q,l,k,z;W(rb,if(fgetc(F)=='P')G(i,0,0)}G(w,1,w<1)}G(h,1,h<1)}G(y,1 +,y-255)}L=n=n<1?1:n>w*h?w*h:n;K=S=(s=w*b)+b;K=sizeof(*X)*L+(u=K*h+ +K)*9;if(K-(L=(size_t)K)||!(t=malloc(K)))break;X=P=O=t+u;d=O=P+n;if +(i<4)for(;x<s*h;)G(i,1,(d[x++]=i,i>>=8))}else i=h-fread)if(i)break +;;for(X->x=X->y=j=0;j<b;j++)for(x=j-S,z=j-b;x<S*h;x+=b)t[x+S]=x<0? +y=0:t[x]+(u=y--?u+d[z+=b]:(y=w,0));;X->w=w;X->h=h;A for(;N=X=P,U&& +++i<n;){for(U=j=0;j++<i;X++)U=X->d>U?(N=X)->d:U; o=*N;v=o.w;q=o.h; +x=o.x;y=o.y;H(b,S,v,q,e,k)H(S,b,q,v,f,l)e<f?o.y+=N->h=l,o.h-=l:(o. +x+=N->w=k,o.w-=k);*X=o;A X=N;A}for(;i--;X++)B(,=);}W(wb,fprintf(F, +"P6\n%i %i\n255\n",c=w,(int)h);fwrite)free(t);return 0;}return 1;} diff --git a/ioccc/2020/kurdyukov2/sample.jpg b/ioccc/2020/kurdyukov2/sample.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c6493c79dc1fb92133f23c64906c43378cb66e07 Binary files /dev/null and b/ioccc/2020/kurdyukov2/sample.jpg differ diff --git a/ioccc/2020/kurdyukov3/Makefile b/ioccc/2020/kurdyukov3/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1ac45a87c2036b9bbec5d1811d95fa69a509134b --- /dev/null +++ b/ioccc/2020/kurdyukov3/Makefile @@ -0,0 +1,585 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-shorten-64-to-32 -Wno-sign-conversion -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +CSTD= -std=c11 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o +DATA= input.txt +TARGET= prog +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/kurdyukov3/compile_commands.json b/ioccc/2020/kurdyukov3/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..6db508db2a39e4f1ed91f37be41e37b758dd7888 --- /dev/null +++ b/ioccc/2020/kurdyukov3/compile_commands.json @@ -0,0 +1,18 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/kurdyukov3/hint.text b/ioccc/2020/kurdyukov3/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..86fee32d1ea0576327198bfef654df1317065965 --- /dev/null +++ b/ioccc/2020/kurdyukov3/hint.text @@ -0,0 +1,48 @@ +# Bset slaml prragom + +Ilya Kurdyukov +<https://github.com/ilyakurdyukov> +Twitter: @ilyakurdyukov + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog + +### Try: + + # first input to try + echo first input to try | ./prog + + # try reading this output + echo International Obfuscated C Code Contest | ./prog + + # try reading this other output + ./prog < input.txt + +### Selected Judges Remarks: + +It is interesting how well smeonoe can raed txet wtih lots of tyops in it. +How well can you raed porg.c, C prgoarm that is in the shpae of an SD card (or +is it a pnuch crad)? + +## Author's comments: +### Letter Mixer ### + +Compile and try this: + +cat some.input.txt | ./prog + +The program can work with letters that are not represented in English, as long as these letters are encoded in the higher part of the single-byte character set (use `iconv` to convert from UTF-8 and back). + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/kurdyukov3/input.txt b/ioccc/2020/kurdyukov3/input.txt new file mode 100644 index 0000000000000000000000000000000000000000..702b7a0e203d891899d3bf4de799a005842293a2 --- /dev/null +++ b/ioccc/2020/kurdyukov3/input.txt @@ -0,0 +1 @@ +Using the incredible power of the human brain, according to research at Cambridge University, it doesn't matter in what order the letters in a word are, the only important thing is that the first and last letter be in the right place. The rest can be a total, mess and you can read it without a problem. diff --git a/ioccc/2020/kurdyukov3/prog.c b/ioccc/2020/kurdyukov3/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..e3f5081232ce99df4c04aec41f4c5f98e9467904 --- /dev/null +++ b/ioccc/2020/kurdyukov3/prog.c @@ -0,0 +1,14 @@ +#include <time.h> +#include <stdio.h> +#include <stdlib.h> +int main(){unsigned +a,i=1,j=0,t[64];for +(srand(time(0));i;) +j=j?--i<1&&a>>8?0:( +putchar(i?t[j]:a),i +++)?t[j]=t[--i],i>2 +?rand()%(i-2)+2:1:0 +:(26>((a=getchar()) +|32)-97||1==a>>7)&& +i<64?t[i++]=a,0:1;} + diff --git a/ioccc/2020/kurdyukov3/prog.extra.c b/ioccc/2020/kurdyukov3/prog.extra.c new file mode 100644 index 0000000000000000000000000000000000000000..8195ef2d02cb0ace88461ed26783c63ecc7a0db8 --- /dev/null +++ b/ioccc/2020/kurdyukov3/prog.extra.c @@ -0,0 +1,80 @@ +#include <time.h> +#include <stdio.h> +#include <stdlib.h> + +#ifndef IDX +#define IDX 1 +#endif +#if IDX==1 // square + + int main(){;unsigned + a,i=1,j=0,t[256];for + (srand(time(0));i;)j + ?(--i||~a>>8?putchar + (i?t[j]:a),i++:0)?t[ + j]=t[--i],j=i>2?rand + ()%(i-2)+2:1,1:j--:( + a=getchar(),(1==a>>7 + ||26>(a|32)-97)&&256 + >i?t[i++]=a,0:j++);} + +#elif IDX==2 + + int main(){;unsigned + a=0,i,j,t[256];srand + (time(0));for(;256>a + ;){for(i=j=0;(26>((a + =getchar())|32)-97|| + 1==a>>7)&&i<256;)t[i + ++]=a;;for(;i||~a>>8 + ?putchar(i?t[j]:a),i + --:0;j=i>1?rand()%(i + -1)+1:0)t[j]=t[i];}} + +#elif IDX==3 // round + + int main() + {unsigned a,i=1, + j=0,t[64];for(srand( + time(0));i;)j?(--i|| + ~a>>8?putchar(i?t[j]:a + ),i++:0)?t[j]=t[--i],j + =i>2?rand()%(i-2)+2:1, + 1:j--:(a=getchar(),( + 26>(a|32)-97||1==a>> + 7)&&i<64?t[i++]= + a,0:j++);} + +#elif IDX==4 + + int main() + {unsigned a,i,j= + a=0,t[64];for(srand( + time(0)),i=0;~a>>8;) + {for(;a=getchar(),(26> + (a|32)-97||1==a>>7)&&i + <64;)t[i++]=a;;for(;!i + &&a>>8?0:putchar(i?t + [j]:a),i;j=i>1?rand( + )%(i-1)+1:0)t[j] + =t[--i];}} + +#elif IDX==5 // profile + + int main + (){;unsigned + a=0,i,j,t[64]; + srand(time(0)) + ;for(;a<256;~a + >>8?putchar(a) + :0){for(i=j=0; + a=getchar(), + ((a|32)-97 + <26||a>> + 7==1)&&i + <64;)t[i++]=a; + for(i-=1;i+1;putchar(t[j]) + ,t[j]=t[i--],j=i?rand()% + i+1:0);}return!a;} + +#endif diff --git a/ioccc/2020/kurdyukov3/prog.orig.c b/ioccc/2020/kurdyukov3/prog.orig.c new file mode 100644 index 0000000000000000000000000000000000000000..c05673e7ce8afeed7c75915fa710bcc6cdfa7b96 --- /dev/null +++ b/ioccc/2020/kurdyukov3/prog.orig.c @@ -0,0 +1,16 @@ +#include <time.h> +#include <stdio.h> +#include <stdlib.h> +#define M(P,F,J)in\ +t main(){unsigned \ +a=0,i,j,t[64];F(sr\ +and(time(0));~a>>8\ +;a>>8?0:P(a)){F(i=\ +j=0;a=getchar(),~i\ +>>6&&(a>>7==1||(a|\ +32)-97<26);)t[i++]\ +=a;F(i--;i+1;j=i?r\ +and()%i+1:0)P(J),J\ +=t[i--];}return 0;} +M(putchar,for,t[j]) + diff --git a/ioccc/2020/kurdyukov4/Makefile b/ioccc/2020/kurdyukov4/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..cbbc8355e31c13a6a4b7bf22c6f4f2c8178db607 --- /dev/null +++ b/ioccc/2020/kurdyukov4/Makefile @@ -0,0 +1,587 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-comma -Wno-implicit-int-conversion -Wno-shorten-64-to-32 -Wno-sign-conversion \ + -Wno-conversion -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +CSTD= -std=c11 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o +DATA= Eugene_Onegin.txt Shakespeare.txt +TARGET= prog +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + +${DATA}: + ${CURL} -o $@.gz http://ioccc.org/2019/mills/$@.gz && ${GUNZIP} $@.gz + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} ${DATA} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/kurdyukov4/compile_commands.json b/ioccc/2020/kurdyukov4/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..6db508db2a39e4f1ed91f37be41e37b758dd7888 --- /dev/null +++ b/ioccc/2020/kurdyukov4/compile_commands.json @@ -0,0 +1,18 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/kurdyukov4/hint.text b/ioccc/2020/kurdyukov4/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..fca9c0865fbffa09dd227fe30b0646d0f219d8ea --- /dev/null +++ b/ioccc/2020/kurdyukov4/hint.text @@ -0,0 +1,110 @@ +# Best abuse of lámatyávë + +Ilya Kurdyukov +<https://github.com/ilyakurdyukov> +Twitter: @ilyakurdyukov + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog text_file output_length context_length random_seed + +### Try: + + ./prog Shakespeare.txt 2000 10 1 + ./prog Shakespeare.txt 2000 9 1 + ./prog Shakespeare.txt 2000 8 1 + # ... Why does it get progressively slower when the context length decreases? + + ./prog Eugene_Onegin.txt 2000 10 1 + # For those not knowing Russian, just to see how the UTF-8 characters are handled + +(*Performance depends on the number of same hashes found.* +*Too many identical strings if the context length is small. author*) + +### Selected Judges Remarks: + +We were able to write our own program performing the same trick +using the (still non-standard, for some reason) library function `memmem`, +but that way it works too fast regardless of the context length, and it's much less fun. + +(*Wow, amazing! Very fast, but there is a drawback to randomness.* +*If some string only appears after half the input, the first instance* +*of this string will have a 50% chance of occurrence.* +*Example:* + + echo "00000000000000000000 01 02 02 02 02 02 02" > test.txt + ./prog test.txt 1000 2 123 + # more twos in output + ./rand test.txt 1000 2 123 + # more ones in output + +*But this will happen very rarely on real data. author*) + +Try using the same random seed and varying the context size. + +## Author's comments: +### Building + + cc prog.c -o prog + +### Usage + +This program generates random text from the provided dictionary using a Markov chain, outputs to `stdout`. + + ./prog input.txt 2000 10 12345 + +Parameters are: + +1. dictionary filename +Need at least the size of the book, the more the better (1Mb), you can concatenate several books into one file. This should be a text file (not `.doc`/`.pdf`). You can feed with books in `.fb2` format, metadata is filtered. Whitespace characters is also filtered. For languages other than English, it's better to use ANSI encoding. You can use UTF, but you need to increase chain length (if one ANSI character is encoded as two UTF bytes, then multiply chain length by two). + +2. bytes to generate (limited at 1Mb) + +3. chain length +Randomness and performance depend inversely on this parameter and the size of the dictionary. If you feel that bytes are generated too slowly, then you need to increase the length of the chain. This length means that any part of the output of this size in bytes exists somewhere in the dictionary. + +4. random seed + +### Example + +You can try this with the inputs provided with `2019/mills` from the IOCCC winners. + + $ ./prog shakespeare.txt 2001 10 12345 + r sons, wives for them, as the hope I had it. This is the way they be not too ra + sh a trial of you only. Therefore will not out of door? Nurse: Marry, bachelor, + Have other some, he is in Rome: but where is Warwick frowns at his. PRINCE EDWAR + D: Where is the light: But I will watch thy waking, what work he makes Amongst y + ou? Come, sirs, We shall write to you, fortune and The hazard of much blood. I w + ould to heaven, respective lenity, And fire-eyed fury be my convoy in the senten + ced; 'tis too horrible, so bloody on the banks If they were created, Would bring + them to our presence? FLORIZEL: And those his golden crown, What is six winters + ? they are but Lewis and Warwick bids you come too late come from the king's fri + end, and will do't; for, look you, sir, For still thy true servitor: I will rend + an oak And peg thee in his knotty entrails till Thou hast hazel eyes: what eye + but such an eye would spy out such a day to-morrow, or next day: He is within th + e limit of the like, forsworn to love, Send her a story of more woe Than this is + a merry ballad, but a very pretty one. MOPSA: Thou hast amazed me, My name is E + lbow: I do lean upon, Now thou art: Thy tears are womanish; thy wild acts denote + The unreasonably: come, you must: and there, I then do't to them? VOLUMNIA: Now + the red pestilence hangs in our aim, which is yours. What is't your honour, as + in war, since then, You have said before: My child is dead; or 'twere not 'long + of him; but he, like you, lads; about your ears it is Menenius? Second Officer: + Come, come, young wanton and effeminate boy, Takes on the hungry beach Fillip th + e stars Shall bitterly begin his wooing that we have in hand are angry And frown + ing brow to brow, ourselves, Still your own affections are devised, As blanks, b + enevolences, and I thank thee for it. KING HENRY VI: Master lieutenant comes. Ma + ster lieutenant comes. Master lieutenant, pray you,-- CORIOLANUS: What's that to + him? CHRISTOPHER: At Pembroke, Sir James Blunt, And Rice ap Thomas with a virtu + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/kurdyukov4/prog.c b/ioccc/2020/kurdyukov4/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..211226fbb997f5c5d9f75c25ab75c5a2d5f676b2 --- /dev/null +++ b/ioccc/2020/kurdyukov4/prog.c @@ -0,0 +1,25 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#define R (z=a=(s*=S)>>31)*n>>32;for( +#define K(x) ))||fseek(F,0,SEEK_##x)|| +int main(int c,char**V){int k,l,p,i,x,y +,n,q;uint64_t s,S=5,z;uint32_t*h,a,t[512 +];while(c++==5){uint8_t*m;void*F;x=atoi(V +[2]);y=atoi(V[3]);s=atoi(V[4]);if(x>>20||( +#define H(b,x) memset b{for(a=i=0;i<y;)a=(\ +a^m[x+i++])*79764919;for(;(i=h[a&q])^-1;a++) +y-1)>>7||!(F=fopen(V[q=1],"rb"K(END)y>(n=fte\ +ll(F K(SET)!(m=malloc(n+y))||fread(m,1,n,F)-n +||n>>29)break;;for(fclose(F);S*5>S;)S*=5;for( +i=k=l=0;i<n;)if('_'-(a=m[i++])){if(a=='<')for +(a=' ';i<n&&m[i++]-'>';);;if((a-' '&&a-'\n'&& +a-'\r'&&a-'\t')||k-(a=' ')) m[l++]=k=a;};n=l; +memcpy(m+l,m,y);for(;l*3>q;)q+=q;if((h=malloc +(4*q))){H((h,-1,4*q--);for(k=0;k<l;h[a&q]=k++ +),k);}p=R;x--;p=p-l?p:0){H((t,n=0,8<<8);,p)if +(!memcmp(m+p,m+i,y))k=m[i+y]*2,t[k++]++,n++,t +[k]=i;}n=R k=-1;n>=0;)n-=t[++k*2];putchar(k); +p=t[k+k+1]+1;}putchar('\n');c=0;}}return!!c;} + diff --git a/ioccc/2020/kurdyukov4/rand.c b/ioccc/2020/kurdyukov4/rand.c new file mode 100644 index 0000000000000000000000000000000000000000..638042c10b6b8a2ae4d091f98c455c2a9fafb380 --- /dev/null +++ b/ioccc/2020/kurdyukov4/rand.c @@ -0,0 +1,47 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +main(int c, char *v[]) { + FILE * f; + int flen, ctxt, osize, pos, npos, i, k, l; + char * m, *loc; + char a; + if (c != 5) exit(1); + f = fopen(v[1], "r"); + if (!f) exit(1); + osize = atoi(v[2]); + ctxt = atoi(v[3]); + srandom(atoi(v[4])); + fseek(f, 0, SEEK_END); flen = ftell(f); fseek(f, 0, SEEK_SET); + if (ctxt < 1 || ctxt >= flen) exit(1); + + m = malloc(flen + flen + ctxt); + if (!m) exit(1); + fread(m, flen, 1, f); + + for (i = k = l = 0; i < flen;) + if ('_' - (a = m[i++])) + { + if (a == '<') + for (a = ' '; i < flen && m[i++] - '>';);; + if ((a - ' ' && a - '\n' && + a - '\r' && a - '\t') || k - (a = ' ')) + m[l++] = k = a; + }; + flen = l; + + memcpy(m+flen, m, flen + ctxt); + pos = random() % flen; + for (i = 0; i < osize; ++i) { + npos = random() % flen; + // find the context at pos starting from npos + loc = memmem(m+npos, flen+ctxt-1, m+pos, ctxt); + if (!loc) puts("I'm lost!!!"), exit(1); + npos = (loc-m) % flen; + putchar(m[npos]); + pos = npos+1; + } + putchar('\n'); +} + diff --git a/ioccc/2020/otterness/Makefile b/ioccc/2020/otterness/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..dc35e1500abdfbde7b1a20492352e76880f4d5b8 --- /dev/null +++ b/ioccc/2020/otterness/Makefile @@ -0,0 +1,588 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-implicit-int-conversion -Wno-missing-prototypes -Wno-missing-variable-declarations \ + -Wno-shorten-64-to-32 -Wno-sign-conversion -Wno-unreachable-code-return -Wno-conversion \ + -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +#CSTD= -std=c11 +CSTD= -std=c99 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o +DATA= +TARGET= prog +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/otterness/compile_commands.json b/ioccc/2020/otterness/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..04a602421896b9c3d47101022593a74d576befa2 --- /dev/null +++ b/ioccc/2020/otterness/compile_commands.json @@ -0,0 +1,18 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c99", + "-Wall", + "-Wextra", + "-pedantic", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/otterness/hint.text b/ioccc/2020/otterness/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..28a3c57f95bf4a74db8f26cd2a8d625c47a87d97 --- /dev/null +++ b/ioccc/2020/otterness/hint.text @@ -0,0 +1,153 @@ +# Most percussive + +Nathan Otterness +<https://github.com/yalue> + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog < input.mid > output.mid + +### Try: + + wget -O cvikl.mid 'http://www.kunstderfuge.com/-/midi.asp?file=beethoven/symphony_6_1_(c)cvikl.mid' + ./prog < cvikl.mid > output.mid + + # Play output.mid with your favorite player + wget -O entertainer.mid https://www.midiworld.com/download/3857 + ./prog < entertainer.mid > output2.mid + # Play output.mid with your favorite player + +### Selected Judges Remarks: + +In an entry that boasts not using literals, one would expect to see straightforward ways to produce +small integers like `!(x^x)<<!(x^x)`, etc. but this entry is trickier than that. Deciphering what it does, +apart from reading stdin and writing to stdout, would take a while. + +While doing that, you can be audially *entertained* by a sample of its output. + +## Author's comments: +### MIDI "boots and cats" + +This program seeks to automatically "improve" standard MIDI files (.mid) by +adding an extra track that provides a driving drum beat to bring some +excitement into boring video-game music rips or classical music sequences that +otherwise only see the light of day when modern musicians import them into FL +Studio to copy a few chords. + + +#### Prerequisites + +If you're not using Windows Media Player or already familiar with MIDI files, +you may need to install some additional software to be able to listen to them. +For example, on Ubuntu, I was able to play them in VLC after installing +`vlc-plugin-fluidsynth` and `fluid-soundfont-gm`. + +You can obtain MIDIs in many places, but I mostly tested the program using +files I found [here](http://www.kunstderfuge.com/beethoven/variae.htm#Symphonies). +However, as discussed under the Limitations heading below, not all of them +work correctly. I will admit to having used +`http://www.kunstderfuge.com/-/midi.asp?file=beethoven/symphony_6_1_(c)cvikl.mid` +for most of my testing. + + +#### Usage + +Compile the program using the following command (I tested this using both +`clang` and `gcc`): +``` +$CC -pedantic -Wall -Werror -Wextra -O3 -o prog prog.c +``` + +The program expects a MIDI on stdin, and writes a modified MIDI to stdout: +``` +./prog <input.mid >output.mid +``` + +If the program encounters an error, no output will generally be produced, and +it will exit with a specific status code. Meanings of the various status codes +are listed below, under the "Program error codes" heading. On success, the +program exits with a code of 0. + + +#### Limitations + + 1. The program does not support MIDI files over 4 MB (specifically, it will + not take input files larger than 2^22 - 1 bytes). This is unlikely to be a + big limitation in practice, since even lengthy MIDIs are rarely over a + couple hundred KB. + + 2. Not all MIDIs set (or *correctly* set) their timing information, which will + lead to the tempo of the drum beat not matching the track. This will be + especially true for "live performance" .mid files. + + 3. There may be some types of MIDI messages that the program is unable to + correctly parse, but I have rarely seen this in practice. The largest + cause of program failures, in my experience, has been Limitation 2. + + +#### Obfuscation notes + +I had one primary goal when writing this program: include no C literals +whatsoever. The final C file includes no numerical, string, or character +literals. Instead, all literals have been replaced with a handful of global +variables, which are occasionally modified throughout the file to prevent +simple uses of find-and-replace. + +So, in a sense, this obfuscation is simply an intentional use of global +variables' classic problem: absolute spaghetti code. The absence of any sort +of literals has the added benefit of forcing any would-be reader to trace the +contents of many variables starting from `main`, since, without literals, very +little of the code gives any inherent visual cues as to its purpose. + +I already took the liberty of running `prog.c` through `clang-format`, since it +still fits in the size limit and the formatting of the code was never intended +to be an obfuscation technique here. + + +#### Other remarks + +MIDI files are generally divided up into one or more "tracks" that play +concurrently. While it is easy to find the positions of each of these tracks +in the file, figuring out the amount of time each track is supposed to play is +more difficult, and requires parsing every track in its entirety. This means +that generating a drum beat that covers the entire piece of music requires +parsing every track (the entire file) in order to determine the longest track. + +Once the program has determined the longest track in the file, it generates a +new track, containing the simple 4-note percussion sequence, to match the +length (in beats) of the longest-running track. It appends the new track onto +the end of the file, taking care to update the file header, as well. + + +### Program error codes + +If the program encounters an error, it will exit with a nonzero code. The error +codes can be interpreted as follows: + + - `1`: Encountered an invalid MIDI variable-length integer in the input. + - `2`: Attempted to write an invalid MIDI variable-length integer to output. + (This would be an internal error). + - `3`: Encountered an unsupported MIDI event in the input. + - `4`: Encountered a bad MIDI track header in the input. + - `5`: The input MIDI file uses SMPTE time division, which isn't supported. + - `6`: Failed allocating a temporary buffer to hold a single copy of our "beat" + messages. + - `7`: Failed allocating a buffer to hold the new track data. + - `8`: Failed allocating a buffer to hold the input file. + - `9`: The input file was too large. + - `10`: The input file's MIDI header was incorrect (but this isn't checked + very thoroughly). + + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/otterness/prog.c b/ioccc/2020/otterness/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..829b6bfe6f062b5391908f3296158c0c71d4f118 --- /dev/null +++ b/ioccc/2020/otterness/prog.c @@ -0,0 +1,226 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#define P(a, b) fwrite(a, b, !!a, stdout) +typedef uint8_t u1; +typedef uint16_t u2; +typedef uint32_t u4; +u4 k, l, n; +u1 m, o, p, q, r, s, *t, *u; + +u2 A(u1 *c) { return *(c + !!c) | (u2)(*c) << l; } + +void B(u1 *c, u2 a) { + *c++ = a >> l; + *c = a; +} + +int C(u1 *c, u4 *a) { + u1 b, d = k; + s = l--; + *a = k++; + for (; d<s>> k; d++) { + b = d[c]; + *a |= b & p; + if (!(b >> l)) { + d += k--; + l = s; + return d; + } + *a = *a << l; + } + exit(!k); + return p; +} + +u1 D(u4 a) { + u1 b = k++; + u1 c = l - k; + if (a) { + b = k; + while (a >>= k) b++; + } + k = k ? !k : k; + return b / c + !!(b % c); +} + +int F(u4 a, u1 *c) { + u1 b = D(a); + *c = s - l--; + r = q / n; + if (!a) return b; + if (b > r) exit(o); + c += b; + c--; + while (a) { + *c = a & p; + a = a >> l; + c--; + } + l = s; + return b; +} + +u1 *G(u1 *c, u1 *a) { + u4 d; + u1 b, e; + m = m < p ? p << q : m; + q = q < n + o ? p >> q : q; + e = *c; + if (e == m || e == m + q) { + *a = k; + c++; + c += C(c, &d); + return c + d; + } + if (e == (m | p)) { + *a = k; + c++; + c++; + c += C(c, &d); + return c + d; + } + l /= o; + if (e >> q) { + b = *c; + c++; + *a = b; + } else { + b = *a; + } + e = b >> l; + if (e < s || e > l + s) exit(n); + if (e != l + s && e != l + o) c++; + c++; + l = s; + return c; +} + +u1 *H(u1 *c, u4 *a) { + u4 b, e, h = q, i = m; + u1 *d, f = k; + *a = k; + q = q / n; + m = p - m + p / m; + if (n[c] != m) exit(q); + b = (u4)A(c + q) << q * q | A(c + (m >> q)); + c += l; + d = c + b; + while (c < d) { + c += C(c, &e); + *a += e; + c = G(c, &f); + } + q = h; + m = i; + return c; +} + +u4 I(u1 *c, u4 a) { + u4 e, b, d = k; + for (e = k; e < a; e++) { + c = H(c, &b); + if (b > d) d = b; + } + return d; +} + +u1 *J(u1 *c, u4 a, u4 b) { + u1 d, e; + if (l > o) { + o = (--s - o) << r; + l = p % (s + o); + r = o / l; + n = l / r; + m = o / n; + } + d = l + r; + e = o; + if (!(a % m)) { + d = l - m; + e = o + l; + } else if ((a % m) == r) { + d = l; + e = n + o; + } + k[t] = d; + r[t] = e; + *u = d; + memcpy(c, t, b); + return c + b; +} + +void K(u1 *c, u4 a) { + u1 *b, *d; + u2 e, f; + u4 g, h, i, j; + o = n ^ k; + m = l; + l = o << o; + f = A(c + l + o); + e = A(c + l + o + o) >> k--; + p = ~k++; + p >>= k--; + q = p >> n; + if (e >> q--) exit(n + o); + g = I(c + q--, f) / e; + i = n + o + D(e); + if (!(t = malloc(i))) exit(n * o); + j = g * i + q; + b = malloc(j); + r = --l; + l++; + if (!b) exit(r); + *b = l << n | q; + *(!k + b) = *b + r; + n[b] = (*b << n) + n; + o[b] = n[b] + r--; + B(b + n * o, j - l); + B(b + o * o, (j - l) >> o * l); + d = t; + *d++ = k; + *d++ = r * r; + m = p / (n + o); + *d++ = p - m - o; + d += F(e, d); + u = d; + *d++ = r * r; + *d = k; + d = b + l; + *d++ = k++; + *d++ = p + q + q; + memcpy(d, t + k, i - k); + d += i - k; + for (h = k; h < g; h++) d = J(d, h, i); + l = (o + m) / s - m; + o = r; + *d++ = --k; + *d++ = ~k; + *d++ = p / o - o * l; + *d = k++; + *(l + p + c) = k; + B(c + l + o, f + k); + P(c, a); + P(b, j); +} + +int main() { + u4 a, b; + u1 *c; + k = !!stdin; + n = k + k + k; + l = k << n; + m = l; + l = (l | l >> (k + k)) << k; + b = k << l; + c = malloc(b); + if (!c) exit(m); + a = fread(c, k, b, stdin); + l = (m << k) + m + k; + if (a >= b) exit(l / n + k); + if ((n[c] != l << (k + k)) || ((m - k)[c] != n + n)) + exit((m << k) - (n << k)); + K(c, a); + return !b; +} diff --git a/ioccc/2020/rules.txt b/ioccc/2020/rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..6ce9a93cf784c46e1b0e77d5ff76575b3fe39dd0 --- /dev/null +++ b/ioccc/2020/rules.txt @@ -0,0 +1,278 @@ +| 27th International Obfuscated C Code Contest Official Rules + +| Copyright (C) 2006-2019 Leonid A. Broukhis, Simon Cooper, Landon Curt Noll + +All Rights Reserved. Permission for personal, education or non-profit use is +granted provided this this copyright and notice are included in its entirety +and remains unaltered. All other uses must receive prior permission in +writing from the contest judges. + + Obfuscate: tr.v. -cated, -cating, -cates. 1. a. To render obscure. + b. To darken. 2. To confuse: his emotions obfuscated his + judgment. [LLat. obfuscare, to darken : ob(intensive) + + Lat. fuscare, to darken < fuscus, dark.] -obfuscation n. + obfuscatory adj. + + +| This rules file is version 2019-06-15-v27. + +Most of the changes from the previous IOCCC rule set have +been marked with a "|" on the left hand side of the line. + + +GOALS OF THE CONTEST: + + * To write the most Obscure/Obfuscated C program under the rules below. + * To show the importance of programming style, in an ironic way. + * To stress C compilers with unusual code. + * To illustrate some of the subtleties of the C language. + * To provide a safe forum for poor C code. :-) + + This IOCCC runs from: + +| 2019-Dec-26 06:01:41 UTC + to: +| 2020-Mar-15 06:26:49 UTC + + Until the start of this IOCCC, these rules, guidelines and iocccsize.c tool + should be considered provisional BETA versions and may be adjusted + at any time. + + The IOCCC submission URL is: + + https://submit.ioccc.org/ + +| The submit URL should be active on or slightly before 2020-Jan-15 12:21:37 UTC. + Please wait to submit your entries until after that time. + + The official rules, guidelines and iocccsize.c tool will be available + on the official IOCCC web site on or slightly before start of this IOCCC. + Please check the IOCCC web site "How to enter" link: + + http://www.ioccc.org/index.html#enter + + on or after the start of this IOCCC to be sure you are using the correct + versions of these items before using the IOCCC entry submission URL. + + +RULES: + + To help us with the volume of entries, we ask that you follow these rules: + + 1) Your entry must be a complete program. + +| 2) This size rule requires your entry to satisfy BOTH rule 2a and rule 2b: + + 2a) The size of your program source must be <= 4096 bytes in length. + + 2b) When your program source is fed as input to the current IOCCC size + tool, and the IOCCC size tool -i command line option is used, the + value printed shall not exceed 2053. + + The source to the current IOCCC size tool is found at this URL: + +| http://www.ioccc.org/2020/iocccsize.c + + 3) Submissions should be performed using the instructions outlined at: + + https://submit.ioccc.org/ + +| The submit URL should be active on or slightly before 2020-Jan-15 12:21:37 UTC. + Please wait to submit your entries until after that time. + + 4) If your entry is selected as a winner, it will be modified as follows: + + Your 'build' instructions will be incorporated into a makefile. + + Your source code will be the file prog.c. The compiled binary + will be called prog. + + 5) Your entry must not modify the content or filename of any part of your + original entry including, but not limited to prog.c, the Makefile + (we create from your how to build instructions), as well as any data + files you submit. + + If you entry wishes to modify such content, it must first copy the + file to a new filename and then modify that copy. + + 6) I am not a rule, I am a free(void *man)! + +| while (!understand(ioccc(rule(you(are(number(6))))))) { ha_ha_ha(); } + + 7) The obfuscated C program must be an original work that you own. + + You (the authors) must own the contents of your submission OR + you must have permission from the owners to submit their content + under the Creative Commons Attribution-ShareAlike 3.0 Unported + (CC BY-SA 3.0) license (see rule 18). + + If you submit any content that is owned by others, you MUST + detail that ownership (i.e., who owns what) and document the + permission you obtained. + + Please note that the IOCCC size tool is not an original work. + +| 8) Entries must be received prior to the end of this IOCCC which is: + +| 2020-Mar-15 06:26:49 UTC + + A confirmation of submission will be sent to the submitter + email address before the close of the contest. + +| 9) Each person may submit up to and including 8.000000 entries per contest. + Each entry must be submitted separately. + + 10) Entries requiring human interaction to be initially compiled are + not permitted. + + 11) Programs that require special privileges (setuid, setgid, super-user, + special owner, special group, etc.) are still highly discouraged. We + do not guarantee these functions will behave as you expect on our test + platforms. If your program needs special permissions please document + them in the remarks file. + + 12) Legal abuse of the rules is somewhat encouraged. An entry that, in + the opinion of the judges, violates the rules will be disqualified. + Entries that attempt to abuse the rules must try to justify why + their rule abuse is legal in the remarks file. + + 13) Any C source that fails to compile because of unescaped octets with + the high bit set (octet value >= 128) will be rejected. + + 14) Any C source that fails to compile because of lines with trailing + control-M's (i.e., lines with a tailing octet 015) will be rejected. + + Please do not put trailing control-M's on remarks file lines. + Please check to be sure, before submitting, that you have removed + any control-M at the end of remark file lines. + + 15) When you submit your entry you must have a valid email address + that can both send and receive email. The online submission + method is a two phase process that requires the use of an + approval code. This code will be emailed to you as part of + phase 1. + + Entries submitted without a working or valid email address will + be disqualified. + + The judges are not responsible for delays in email, please plan + enough time for one automated exchange of email as part of your + submission. + + After your email address has been confirmed, the submission code will + be valid for submitting and editing the entry for the lifetime of the + competition. + + 16) You are STRONGLY encouraged to submit a previously unpublished and + original entry. Submissions that are similar to previous entries are + discouraged. As we judge anonymously, submissions that have already + been published may be disqualified. + + 17) The total size of your submission: the sum of the size of the program, + hints, comments, build and info files MUST be less than or equal + to 1048576 octets in size. + + 18) The entirety of your entry must be submitted under the Creative Commons + Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0): + + http://creativecommons.org/licenses/by-sa/3.0/ + + You must not submit anything that cannot be submitted under that license. + + 19) The remarks file must be written in markdown format. See: + + http://daringfireball.net/projects/markdown/basics + + for more information. + + We currently use "Discount" to convert markdown to HTML + + http://www.pell.portland.or.us/~orc/Code/discount/ + + 20) The how to build instructions must be in make form. + + The target of the make file must be called prog. The original + C source file must be called prog.c. + + To invoke the C compiler, use ${CC}. + To invoke the C preprocessor use ${CPP}. + + Do not assume that . (the current directory) is in the $PATH. + + Use a shell command syntax that is compatible with bash. + + Assume that commands commonly found in POSIX-like / Linux-like systems + are available in the search path. + + Do not assume any particular given value of ${CFLAGS} or other + commonly used make variables. + + 21) Your entry must not create nor modify files above the current directory + with the exception of the /tmp and the /var/tmp directories. Your entry + may create subdirectories below the current directory, or in /tmp, + or in /var/tmp provided that "." is not the first octet in any + directory name. + + 22) Catch 22: + + Your source code, data files, remarks and program output must NOT + identify the authors of your code. The judges STRONGLY prefer to + not know who is submitting entries to the IOCCC. + + Even if you are a previous IOCCC winner, catch 22 still applies. + + Identifying the authors of your entry in an obvious way anywhere + within in your code, data, remarks or program output (unless you are + Peter Honeyman or pretending to be Peter Honeyman) will be grounds + for disqualification of your entry. + + Yes, Virginia, we really mean it! + + 23) This prime rule number is reserved for future use. + + 24) Even though 24 is not prime, you should still see rule #23. + +| 25) The IOCCC rule set consists of at least 26 rules. + +| 26) Rule 26 is also a rule. + + +FOR MORE INFORMATION: + + The judging will be done by Leonid A. Broukhis, Simon Cooper, + Landon Curt Noll. + + Please send questions or comments about the contest, to: + +| q.2020@ioccc.org (for questions only!) + + You must include the words: + +| ioccc 2020 question + +| in the subject of your Email message when sending Email to the judges. + + The rules and the guidelines may (and often do) change from year to + year. You should be sure you have the current rules and guidelines + prior to submitting entries. To obtain them, visit the IOCCC web page: + + http://www.ioccc.org + + It has rules, guidelines and winners of previous contests (1984 to date). + + For the updates and breaking IOCCC news, you are encouraged to follow + the twitter handle: + + @IOCCC + + You do not have to be a twitter user to follow @IOCCC. Non-twitter + users should access: + + https://twitter.com/ioccc + + Non-twitter users should force their browsers to reload the above URL + to be sure they are seeing the most recent tweets. + +Leonid A. Broukhis +Simon Cooper +chongo (Landon Curt Noll) /\cc/\ diff --git a/ioccc/2020/tsoj/Makefile b/ioccc/2020/tsoj/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..dc309d6286297e394238b93273950cf0689db236 --- /dev/null +++ b/ioccc/2020/tsoj/Makefile @@ -0,0 +1,592 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-comma -Wno-empty-body -Wno-float-conversion -Wno-implicit-float-conversion \ + -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-shadow -Wno-shorten-64-to-32 \ + -Wno-sign-conversion -Wno-vla -Wno-conversion -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-empty-body -Wno-missing-field-initializers -Wno-misleading-indentation \ + -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-empty-body -Wno-missing-field-initializers \ + -Wno-misleading-indentation -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +#CSTD= -std=c11 +CSTD= -std=c99 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o +DATA= +TARGET= prog +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/tsoj/compile_commands.json b/ioccc/2020/tsoj/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..fc85917ab0cf65956856e7c543b773f01f36a1e6 --- /dev/null +++ b/ioccc/2020/tsoj/compile_commands.json @@ -0,0 +1,22 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c99", + "-Wall", + "-Wextra", + "-pedantic", + "-Wno-empty-body", + "-Wno-missing-field-initializers", + "-Wno-misleading-indentation", + "-Wno-unknown-warning-option", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/tsoj/hint.text b/ioccc/2020/tsoj/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..1460ab298ca027dae03cdfb9a8d3e6ef05f79ad0 --- /dev/null +++ b/ioccc/2020/tsoj/hint.text @@ -0,0 +1,99 @@ +# Most misleading indentation + +tsoj <tsoj.tsoj@gmx.de> +<https://gitlab.com/tsoj> + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog + + +### Try: + + # Make your terminal as large as possible, possibly reduce your font size + # then... + ./prog + +### Selected Judges Remarks: + +This game does not use curses, but you may end up cursing. + +The code is made more difficult to read using an innovative, right justified, +reverse indentation style. + +## Author's comments: +#### Controls +- Movement: +`w`, `a`, `s`, `d` +- Fire: +`space` +- Quit: +`q` +- Pause: +`p`, then use any other key to resume + +``` + /\ + //\\ + / \ +/______\ + /\/\ +``` +#### Compile and run +###### Linux +``` +cc -std=c99 -O3 prog.c -o prog +./prog +``` + +###### Windows +The only way I found to make it work is to use [MSYS2](https://www.msys2.org). When using the MSYS2 shell you can install gcc via pacman. +``` +cc -std=c99 -O3 prog.c -o prog +./prog.exe +``` +#### Warnings +- `-Wno-missing-prototypes` +- `-Wno-shorten-64-to-32` +- `-Wno-sign-conversion` +- `-Wno-implicit-int-float-conversion` +- `-Wno-missing-field-initializers` +- `-Wno-implicit-float-conversion` +- `-Wno-vla` +- `-Wno-float-conversion` +- `-Wno-comma` +- `-Wno-shadow` +- `-Wno-format` +- `-Wno-empty-body` +- `-Wno-misleading-indentation` +- `-Wno-maybe-uninitialized` +- You may experience a mild [motion aftereffect](https://en.wikipedia.org/wiki/Motion_aftereffect) when playing for too long +#### Highscore +Score will be shown in the top left corner. +My best was **156**. If you beat that I'll send you the image of a very expensive chocolate. +#### Features +- Procedural star generation +- Very space-efficient for-loops +- No use of `!=` or `==` +- Smooth rendering even on slow terminals +- Advanced ascii-art +- Cutting edge physics engine and collision detection +- Probably not many segfaults +- Every letter in the English alphabet has a variable or function named after it +- Not a virus +- Runs on my machine +#### Tips +- Adjust your terminal size for different experiences +- Run this program in a virtual console to immerse yourself in the game +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/tsoj/prog.c b/ioccc/2020/tsoj/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..90f81081e5fd17df4eeb1b3d8d310618a0c97603 --- /dev/null +++ b/ioccc/2020/tsoj/prog.c @@ -0,0 +1,60 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <termios.h> +#include <time.h> +#include <unistd.h> +int t(){struct timeval t;gettimeofday(&t,0);return t.tv_usec/1000+t.tv_sec*1000;} + + #define g(x,y,u,v,s)\ + for(int j=0,X=x,Y=y;j<v&&Y+j<h-X/w&&Y>=0&&X>=0;++j)memcpy(&f[Y+j][X],&s[j*u],u) + #define l(x,y,w,h,a,b,c,d)\ + !((x-a>c&&x>=a)||(a-x>w&&a>=x)||(y-b>d&&y>=b)||(b-y>h&&b>=y)) + + int main(){ + struct termios z,o;tcgetattr(0,&z);o=z;z.c_lflag&=~ICANON&~ECHO; + z.c_cc[VMIN]=0;z.c_cc[VTIME]=0;tcsetattr(0,TCSANOW,&z); + srand(time(0));struct winsize v;ioctl(STDOUT_FILENO,TIOCGWINSZ,&v); + int h=v.ws_row,w=v.ws_col,A=w*h/100,l=t(),k,s=0,g=1,i,c=0,L; + struct V{float x,y;}p={w/2,h/2},b={-3*h},a[A],m[A]; + char*r=" /\\ /__\\ ^^ ",*n="o0o0OO",u=0,q,f[h+1][w]; + while(u^'q'){ + float d=(t()-l)*.001; + q=u;do read(0,&u,1);while((u&'p')>=(u|'p')); + l=t();c+=15;i=h*w-1; + K: + L=c*d;L=abs(((i/w)-L)*(i%w)+h*w); + (*f)[i]=L%3+L%5+L%7+L%11+L%13+L%17+L%19>14?32:46; + if(i--)goto K; + u^' '?0:(b.x=p.x+2,b.y=p.y,u=q); + q^'a'?q^'d'?q^'w'?q^'s'?0: + (p.y+=d*15): + (p.y+=d*-15): + (p.x+=d*20): + (p.x+=d*-20); + p.x=p.x<0?0:p.x>=w-4?w-4:p.x; + p.y=p.y<0?0:p.y>=h-3?h-3:p.y; + b.y+=d*-20; + int Y=b.y,X=b.x;Y*w+X>=0?f[Y][X]=64:0; + i=A-1; + L: + k=0;struct V*e=&a[i],*z=&m[i]; + e->x+=d*z->x;e->y+=d*z->y; + l(b.x,b.y,1,1,e->x,e->y,6,4)&&!g?k=1,s++,b.y=-3*h:0; + e->x<0-3||e->x>=w+3||e->y>=h+2||k||g? + e->y=-rand()%h*(1+g), + e->x=rand()%w, + z->x=-8+rand()%15, + z->y=10+rand()%5:0; + l(p.x,p.y,4,3,e->x,e->y,3,2)?u='q':0; + g(e->x,e->y,3,2,n); + if(i--)goto L; + g(p.x,p.y,4,3,r); + *(f[h])=0; + printf("\033[0;4H%s\033[0;0H \033[4D%i\n",&f[0][4],s); + while(t()-l<9);g=0; + } + tcsetattr(0,TCSADRAIN,&o); + } diff --git a/ioccc/2020/yang/Makefile b/ioccc/2020/yang/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a6e0fda855c02c55560fc76489a9596a488220a5 --- /dev/null +++ b/ioccc/2020/yang/Makefile @@ -0,0 +1,587 @@ +#!/usr/bin/env make +# +# 2020 makefile +# +# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis +# is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + +############################# +# shell used by this Makefile +############################# +# +SHELL= /bin/bash + +####################### +# common tool locations +####################### +# +A2P= a2p +AR= ar +ASA= asa +AT= at +ATQ= atq +ATRM= atrm +AWK= awk +BANNER= banner +BASE64= base64 +BASENAME= basename +BATCH= batch +BC= bc +BINHEX= binhex +BISON= bison +BUNZIP2= bunzip2 +BZCAT= bzcat +BZCMP= bzcmp +BZDIFF= bzdiff +BZEGREP= bzegrep +BZFGREP= bzfgrep +BZGREP= bzgrep +BZIP2= bzip2 +BZLESS= bzless +BZMORE= bzmore +C2PH= c2ph +C89= c89 +C99= c99 +CAL= cal +CALC= calc +CAT= cat +CD= cd +CHFLAGS= chflags +CHGRP= chgrp +CHMOD= chmod +CKSUM= cksum +CLANG= clang +CLANG_PLUSPLUS= clang++ +CLEAR= clear +CMP= cmp +COL= col +COLLDEF= colldef +COLRM= colrm +COLUMN= column +COMPRESS= compress +CP= cp +CPIO= cpio +CPP= cpp +CRC32= crc32 +CSH= csh +CSPLIT= csplit +CURL= curl +CUT= cut +C_PLUSPLUS= c++ +C_PLUSPLUS_FILT= c++filt +DATE= date +DC= dc +DD= dd +DF= df +DIFF3= diff3 +DIFF= diff +DIG= dig +DIRNAME= dirname +ECHO= echo +ED= ed +EGREP= egrep +ENV= env +EQN= eqn +ETAGS= etags +EXPECT= expect +EXPR= expr +FALSE= false +FGREP= fgrep +FILE= file +FIND2PERL= find2perl +FIND= find +FLEX= flex +FLEX_PLUSPLUS= flex++ +FMT= fmt +FOLD= fold +FS_USAGE= fs_usage +FUNZIP= funzip +FUSER= fuser +GCC= gcc +GDIFFMK= gdiffmk +GENCAT= gencat +GENSTRINGS= genstrings +GETOPT= getopt +GETOPTS= getopts +GINDENT= gindent +GNUMAKE= gnumake +GREP= grep +GROFF= groff +GROFFER= groffer +GROG= grog +GROPS= grops +GROTTY= grotty +GUNZIP= gunzip +GVIM= gvim +GZCAT= gzcat +GZEXE= gzexe +GZIP_PROG= gzip +G_PLUSPLUS= g++ +H2PH= h2ph +H2XS= h2xs +HASH= hash +HEAD= head +HOSTNAME_PROG= hostname +ICONV= iconv +ID= id +INDENT= indent +INFO= info +JOT= jot +KILL= kill +KSH= ksh +LAST= last +LD= ld +LESSECHO= lessecho +LEX= len +LINK= link +LN= ln +LS= ls +M4= m4 +MAKE= make +MAN= man +MKDIR= mkdir +MKFIFo= mkfifo +MKTEMP= mktemp +MV= mv +NANO= nano +NASM= nasm +NEQN= neqn +NICE= nice +NL= nl +NM= nm +NOHUP= nohup +NROFF= nroff +NSLOOKUP= nslookup +OD= od +OPENSSL= openssl +PASTE= paste +PATCH= patch +PATHCHK= pathchk +PAX= pax +PERL= perl +PICO= pico +PR= pr +PRINTENV= printenv +PS= ps +PTAR= ptar +PTARDIFF= ptardiff +PTARGREP= ptargrep +PWD= pwd +PYDOC= pydoc +PYTHON= python +PYTHONW= pythonw +READLINK= readlink +RENICE= renice +RESET= reset +REV= rev +RI= ri +RM= rm +RMDIR= rmdir +RSYNC= rsync +RUBY= ruby +RVIM= rvim +SAY= say +SCP= scp +SCREEN= screen +SCRIPT= script +SDIFF= sdiff +SED= sed +SEQ= seq +SFTP= sftp +SH= sh +SHA1= sha1 +SHA= sha +SHAR= shar +SHASUM5_18= shasum5.18 +SHASUM= shasum +SIZE= size +SLEEP= sleep +SORT= sort +SSH= ssh +STAT= stat +STRIP= strip +STTY= stty +SUM= sum +SYNC= sync +TABS= tabs +TAIL= tail +TAR= tar +TEE= tee +TEST= test +TFTP= tftp +TIDY= tidy +TIME= time +TOP= top +TOUCH= touch +TPUT= tout +TPUT= tput +TR= tr +TROFF= troff +TRUE= true +TSET= tset +TSORT= tsort +UL= ul +UNAME= uname +UNCOMPRESS= uncompress +UNEXPAND= unexpand +UNIFDEF= unifdef +UNIFDEFALL= unifdefall +UNIQ= uniq +UNITS= units +UNLINK= unlink +UNZIP= unzip +UNZIPSFX= unzipsfx +UPTIME= uptime +UUDECODE= uudecode +UUENCODE= uuencode +UUIDGEN= uuidgen +VI= vi +VIEW= view +VIM= vim +VIMDIFF= vimdiff +W= w +WAIT4PATH= wait4path +WAIT= wait +WC= wc +WHAT= what +WHATIS= whatis +WHICH= which +WHO= who +WHOAMI= whoami +WHOIS= whois +WRTIE= write +XAR= xar +XARGS= xargs +XATTR= xattr +XXD= xxd +YACC= yacc +YES= yes +ZCAT= zcat +ZCMP= zcmp +ZDIFF= zdiff +ZEGREP= zegrep +ZFGREP= zfgrep +ZFORCE= zforce +ZGREP= zgrep +ZIP= zip +ZIPCLOAK= zipcloak +ZIPGREp= zipgrep +ZIPINFo= zipinfo +ZIPNOTE= zipnote +ZIPSPLIT= zipsplit +ZLESS= zless +ZMORE= zmore +ZNEW= znew +ZPRINT= zprint +ZSH= zsh + +# Set X11_LIBDIR to the directory where the X11 library resides +# +#X11_LIBDIR= /usr/X11R6/lib +#X11_LIBDIR= /usr/X11/lib +X11_LIBDIR= /opt/X11/lib + +# Set X11_INCLUDEDIR to the directory where the X11 include files reside +# +#X11_INCDIR= /usr/X11R6/include +#X11_INCDIR= /usr/X11/include +X11_INCDIR= /opt/X11/include + +# CWARN - Silence warnings that ${CWARN} would normally complain about +# CSILENCE -Compiler warnings +# +ifeq ($(CC),clang) + +# clang CSILENCE and CWARN +# +#CSILENCE= +#CSILENCE= -Wno-implicit-int +CSILENCE= -Wno-comma -Wno-format-nonliteral -Wno-implicit-int-conversion -Wno-missing-prototypes \ + -Wno-missing-variable-declarations -Wno-redundant-parens -Wno-shadow -Wno-shorten-64-to-32 \ + -Wno-sign-conversion -Wno-conversion -Wno-unknown-warning-option +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +#CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +else +ifeq ($(CC),gcc) + +# gcc CSILENCE and CWARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} + +else + +# default CSILENCE and WARN +# +CSILENCE= +#CSILENCE= -Wno-implicit-int +# +#CWARN= $CSILENCE} +#CWARN= -Wall $CSILENCE} +#CWARN= -Wall -Wextra $CSILENCE} +CWARN= -Wall -Wextra -pedantic ${CSILENCE} +#CWARN= -Wall -Wextra -Weverything $CSILENCE} +#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE} + +endif +endif + +# compiler standard +# +#CSTD= +#CSTD= -ansi +CSTD= -std=c11 + +# compiler bit architecture +# +# Some entries require 32-bitness: +# ARCH= -m32 +# +# Some entries require 64-bitness: +# ARCH= -m64 +# +# By default we assume nothing: +# +ARCH= + +# defines that are needed to compile +# +CDEFINE= +#CDEFINE= -DIOCCC + +# include files that are needed to compile +# +CINCLUDE= +#CINCLUDE= -include stdlib.h +#CINCLUDE= -include stdio.h +#CINCLUDE= -include stdlib.h -include stdio.h +#CINCLUDE= -I ${X11_INCDIR} + +# optimization +# +# Most compiles will safely use -O2. Some can use only -O1 or -O. +# A few compilers have broken optimizers or this entry make break +# under those buggy optimizers and thus you may not want anything. +# Reasonable compilers will allow for -O3. +# +#OPT= +#OPT= -O +#OPT= -O1 +#OPT= -O2 +OPT= -O3 + +# default flags for ANSI C compilation +# +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} + +# Libraries needed to build +# +LIBS= +#LIBS= -L ${X11_LIBDIR} + +# ANSI compiler +# +# Set CC to the name of your ANSI compiler. +# +# Some entries seem to need gcc. If you have gcc, set +# both CC and MAY_NEED_GCC to gcc. +# +# If you do not have gcc, set CC to the name of your ANSI compiler, and +# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just : +# to disable such programs. +# +CC= cc +#CC= clang +MAY_NEED_GCC= gcc + + +############################## +# Special flags for this entry +############################## +# +OBJ= prog.o +DATA= cppp.cc +TARGET= prog +# +ALT_OBJ= +ALT_TARGET= + + +################# +# build the entry +################# +# +all: ${TARGET} ${DATA} + @${TRUE} + +prog: prog.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + +# alternative executable +# +alt: ${ALT_TARGET} + @${TRUE} + +# data files +# +data: ${DATA} + @${TRUE} + + +############### +# utility rules +############### +# +everything: all alt + +clean: + ${RM} -f ${OBJ} ${ALT_OBJ} + @-if [ -f indent.c ]; then \ + ${ECHO} ${RM} -f indent.c; \ + ${RM} -f indent.c; \ + fi + +clobber: clean + ${RM} -f ${TARGET} ${ALT_TARGET} + @-if [ -e sandwich ]; then \ + ${RM} -f sandwich; \ + ${ECHO} 'ate sandwich'; \ + fi + +nuke: clobber + @${TRUE} + +dist_clean: nuke + @${TRUE} + +install: + @${ECHO} "Surely you are performing, Dr. Science!" + @${TRUE} + +# backwards compatibility +# +build: all + @${TRUE} + +# you may be able to mis-understand the source by reading indent.c +# +indent.c: prog.c + @if which "${GINDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${GINDENT} < $< > $@"; \ + ${GINDENT} < $< > $@; \ + elif which "${INDENT}" >/dev/null 2>&1; then \ + ${ECHO} ${RM} -f $@; \ + ${RM} -f $@; \ + ${ECHO} "${INDENT} < $< > $@"; \ + ${INDENT} < $< > $@; \ + else \ + ${ECHO} "no intent prog found, ident $< yourself, sorry"; \ + ${ECHO} "exit 1"; \ + exit 1; \ + fi + + +################## +# 133t hacker rulz +################## +# +love: + @${ECHO} 'not war?' + @${TRUE} + +haste: + $(MAKE) waste + @${TRUE} + +waste: + @${ECHO} 'haste' + @${TRUE} + +make: + @${ECHO} 'We encourage you to attend a maker faire' + @${TRUE} + +easter_egg: + @${ECHO} you expected to often mis-understand this $${RANDOM} magic + @${ECHO} chongo '<was here>' "/\\oo/\\" + @${ECHO} Eggy and Kitty + +fabricate fashion form frame manufacture produce: make + @${TRUE} + +sandwich: + @if [ `id -u` -eq 0 ]; then \ + ${ECHO} 'Okay.'; \ + ${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \ + ${SHASUM} -a 512256 | \ + ${SED} -e 's/ .*//' > $@; \ + else \ + ${ECHO} 'Reall?!? Make it yourself.'; \ + exit 1; \ + fi + +# Understand the history of the Homebrew Computer Club +# as well as the West Coast Computer Faire and +# you might be confused different. :-) +# +supernova: nuke + @-if [ -r .code_anal ]; then \ + ${RM} -f .code_anal_v6; \ + else \ + ${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \ + fi + @${ECHO} A $@ helps ${MAKE} the elements that help form planets + @${TRUE} + +deep_magic: + @-if [ -r .code_anal ]; then \ + ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + sleep 1; \ + ${ECHO} "Wrong! Do it again!"; \ + fi + @${TRUE} + +magic: deep_magic + @-if [ -r .code_anal ]; then \ + ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \ + else \ + ${ECHO} "If you don't eat yer meat, you can't have any pudding!"; \ + ${ECHO} "How can you have any pudding if you don't eat yer meat?!"; \ + ${ECHO} "p.s. Be cafeful with that axe, Eugene."; \ + fi + @${TRUE} + +# The IOCCC resident astronomer states +# +charon: supernova + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore we continue to tell the IAU that $@ is a planet + +pluto: supernova + ${MAKE} charon + @${ECHO} $@ is a dwarf planet + @${ECHO} dwarf is a type of planet + @${ECHO} therefore, $@ is a planet + @${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them diff --git a/ioccc/2020/yang/compile_commands.json b/ioccc/2020/yang/compile_commands.json new file mode 100644 index 0000000000000000000000000000000000000000..6db508db2a39e4f1ed91f37be41e37b758dd7888 --- /dev/null +++ b/ioccc/2020/yang/compile_commands.json @@ -0,0 +1,18 @@ +[ + { + "arguments": [ + "cc", + "-c", + "-std=c11", + "-Wall", + "-Wextra", + "-pedantic", + "-O3", + "-o", + "prog", + "prog.c" + ], + "directory": ".", + "file": "prog.c" + } +] \ No newline at end of file diff --git a/ioccc/2020/yang/cppp.cc b/ioccc/2020/yang/cppp.cc new file mode 100644 index 0000000000000000000000000000000000000000..17c48ca1ce4eb3511f0e867c3f9ff25dd96e2bb4 --- /dev/null +++ b/ioccc/2020/yang/cppp.cc @@ -0,0 +1,859 @@ +// CPPP stands for "C Pre-PreProcessor", so named because the output +// is meant to be fed into a real C preprocessors before they are +// useful. Not to be confused with CPP (a real C preprocessor) or +// CCCP (something else entirely). +// +// This tool is written to do primarily one thing, which is to +// evaluate files that are heavy on ifdef/ifndef and self-includes, +// and unroll those to something that is more palatable to typical +// preprocessors. To that end, it is able to handle these directives: +// +// if elif else ifdef ifndef endif define undef warning error include +// +// With lots of caveats, such as: +// +// - #if and #elif only works if the expressions are shaped like these: +// #if A % B > C +// #if A > B +// #if A +// +// - #include only works if right hand side evaluates to __FILE__, +// otherwise the directive is copied to output. +// +// - __LINE__ is not preserved. Or rather, they are copied as is. +// So if a __LINE__ moved to a different line after preprocessor +// directives are evaluated, it will take on a different value as +// opposed to whatever they would have been in the original source +// location. +// +// - #define with right-hand side or macro parameters are copied to +// output, otherwise they are evaluated and dropped. The intent is +// to allow the next preprocessor to parse these and do macro +// expansion there, since this tool doesn't do any macro expansion +// on its own. +// +// That's right, no macro expansions. The one thing that is the main job +// for most other preprocessors, we don't do that here. Don't mistake +// this utility for a real preprocessor, it's just a pre-preprocessor. +// But for the one task it is implemented to do, it does so significantly +// faster than GCC or Clang's preprocessors. +// +// Requires compilers that supports C++17 or later. + +#include<ctype.h> +#include<inttypes.h> +#include<stdio.h> +#include<stdlib.h> + +#include<array> +#include<string_view> +#include<string> +#include<unordered_map> +#include<unordered_set> +#include<vector> + +namespace { + +// Maximum depth to avoid runaway includes. +// +// GCC supports 200 and said standard requires at least 15: +// https://gcc.gnu.org/onlinedocs/cpp/Implementation-limits.html +// +// We cap our max inclusion depth at 15 so that this tool can be used +// to flag inputs that might be troublesome for other preprocessors. +static constexpr int kMaxIncludeDepth = 15; + +// List of characters that passes isspace(). +static constexpr char kSpace[] = " \t\r\n\f\v"; + +// List of characters to match start of macro parameter or value. +static constexpr char kSpaceOrLeftParen[] = " \t("; + +// Table of (macro name, macro definition). +// +// Note that there is no place to store macro arguments here. This is +// intentional, since we don't do any macro expansions. +using MacroTable = std::unordered_map<std::string_view, std::string_view>; + +// Preprocessor directives. +enum class Directive +{ + kIf, // arg = expression + kElif, // arg = expression + kElse, + kIfDef, // arg = macro to test + kIfNDef, // arg = macro to test + kEndIf, + kDefine, // arg = macro to insert + kUndef, // arg = macro to remove + kInclude, // arg = filename or macro + kWarning, // arg = output text + kError, // arg = output text + kRawDefine, // arg = input line + kText // arg = input line +}; + +// A single preprocessor instruction step. +struct Operation +{ + // Operation parameters. + Directive directive; + std::string_view arg; + + // Index of next instruction after evaluating conditional expression. + size_t true_branch, false_branch; +}; + +// Debugging stats. +struct Stats +{ + // Number of #include counts. + // + // Number of includes overflowing signed 32bits? It's more likely + // than you think. Although if you did observe this number going + // even above just a few hundred, you are likely going to have a + // terrible experience feeding the same file to a real preprocessor. + int64_t include_count = -1; + + // Number of Operation steps executed, which is roughly the number + // of lines that we didn't skip. + int64_t operation_steps = 0; + + // Maximum level of self-includes observed. + int max_include_depth = 0; +}; + +// Load input from opened file handle and append to output string. +static void LoadInputFromHandle(FILE *infile, std::string *text) +{ + std::array<char, 1024> buffer; + for(size_t read_size;;) + { + read_size = fread(buffer.data(), 1, buffer.size(), infile); + text->append(std::string(buffer.data(), read_size)); + if( read_size < buffer.size() ) + break; + } +} + +// Load input to memory. +static bool LoadInput(const char *file_name, std::string *text) +{ + FILE *infile; + if( (infile = fopen(file_name, "rb")) == nullptr ) + { + fprintf(stderr, "Error reading from %s\n", file_name); + return false; + } + LoadInputFromHandle(infile, text); + fclose(infile); + return true; +} + +// Return list of strings, roughly one string per line except multiline +// comments and preprocessor directives will be coalesced as one string. +static std::vector<std::string_view> TokenizeToLines(std::string *text) +{ + // State machine for parsing various regions of text. + enum class State + { + Normal, + SingleQuotedString, + DoubleQuotedString, + RawString, + SingleLineComment, + BlockComment + }; + State state = State::Normal; + + // List of offsets that are the start of each line. + std::vector<size_t> line_offsets = {0}; + + // r = offset we are reading from, w = offset we are writing to. w <= r. + // + // These indices are used to modify the input string in-place, to + // skip over uninteresting things such as backslash-newline pairs + // and single line comments. + size_t w = 0; + for(size_t r = 0; r < text->size();) + { + const char c = (*text)[r]; + switch( state ) + { + case State::Normal: + // Normal state, check if we are about to enter enclosed things. + if( c == '\'' ) + { + // Single quoted literal. + state = State::SingleQuotedString; + (*text)[w++] = (*text)[r++]; + } + else if( c == '\"' ) + { + // Double quoted literal. + state = State::DoubleQuotedString; + (*text)[w++] = (*text)[r++]; + } + else if( c == 'R' ) + { + // Start a C++11 raw string if we saw a R"( trigram not + // preceded by what might be an identifier. + // + // Note that this is the only kind of raw string we + // support, and not the full R"token( type of raw strings. + if( r == 0 || + (!isalnum((*text)[r - 1]) && (*text)[r - 1] != '_') ) + { + // While C++11 guarantees that we can read +1 past + // the end of a string, it doesn't guarantee that we + // can read +2, so we must check the bounds here + // (unlike other places). + if( r + 2 < text->size() && + (*text)[r + 1] == '\"' && + (*text)[r + 2] == '(' ) + { + state = State::RawString; + } + } + (*text)[w++] = (*text)[r++]; + } + else if( c == '/' ) + { + // Start of comments. + if( (*text)[r + 1] == '/' ) + { + // Single line comments are dropped entirely. + state = State::SingleLineComment; + r += 2; + } + else if( (*text)[r + 1] == '*' ) + { + // Whitespaces inside block comments are preserved, such + // that line numbers and code alignment after the block + // comments are preserved. + state = State::BlockComment; + (*text)[w++] = ' '; + (*text)[w++] = ' '; + r += 2; + } + else + { + (*text)[w++] = (*text)[r++]; + } + } + else if( c == '\\' && (*text)[r + 1] == '\n' ) + { + // Skip over backslash-newline pairs, thus joining backslash + // escaped line breaks. Note that this is only done in + // Normal state. We specifically want to preserve + // backslash-newline pairs inside C++11 raw strings. + r += 2; + } + else + { + // Copy other characters as is, recording offsets to + // next character just after a newline. + (*text)[w++] = (*text)[r++]; + if( c == '\n' ) + line_offsets.push_back(w); + } + break; + + case State::SingleQuotedString: + // Skip over backslash escapes, and end single quoted + // literals on single quotes. + if( c == '\\' ) + { + (*text)[w++] = (*text)[r++]; + } + else if( c == '\'' ) + { + state = State::Normal; + } + (*text)[w++] = (*text)[r++]; + break; + + case State::DoubleQuotedString: + // Skip over backslash escapes, and end double quoted + // literals on double quotes. + if( c == '\\' ) + { + (*text)[w++] = (*text)[r++]; + } + else if( c == '\"' ) + { + state = State::Normal; + } + (*text)[w++] = (*text)[r++]; + break; + + case State::RawString: + // End C++11 raw strings on )" bigram. + if( c == ')' && (*text)[r + 1] == '\"' ) + { + (*text)[w++] = (*text)[r++]; + state = State::Normal; + } + (*text)[w++] = (*text)[r++]; + break; + + case State::SingleLineComment: + // Drop all single line comment contents until the trailing + // newline. Only the final newline is copied to output. + if( c == '\n' ) + { + state = State::Normal; + (*text)[w++] = (*text)[r++]; + line_offsets.push_back(w); + } + else + { + r++; + } + break; + + case State::BlockComment: + // Replace block comments with spaces, and end comments on + // */ bigram. + if( c == '*' && (*text)[r + 1] == '/' ) + { + state = State::Normal; + (*text)[w++] = ' '; + (*text)[w++] = ' '; + r += 2; + } + else + { + // If the byte we are replacing is already a space character, + // then just copy it as is. Otherwise, replace it with a + // normal whitespace. This is meant to preserve layout for + // when block comments are used within a single line. If we + // were to support __LINE__, this may also help in keeping that + // consistent, but since we don't support macro expansions of + // any kind, it doesn't matter. + // + // We don't have to worry about embedded newlines mess up line + // splitting, since line splitting is done by remembering the + // offsets of all newlines outside of all enclosed regions. + // This means something like this works: + // # /* + // */ define NEXT_LINE + if( isspace(c) ) + (*text)[w++] = c; + else + (*text)[w++] = ' '; + r++; + } + break; + } + } + text->erase(w); + + // Build list of lines from line offsets. + std::vector<std::string_view> lines; + if( w > 0 ) + { + lines.reserve(line_offsets.size()); + if( line_offsets.back() != w ) + line_offsets.push_back(w); + for(size_t i = 0; i + 1 < line_offsets.size(); i++) + { + std::string_view l(*text); + l.remove_prefix(line_offsets[i]); + l.remove_suffix(l.size() - (line_offsets[i + 1] - line_offsets[i])); + lines.push_back(l); + } + } + return lines; +} + +// Remove leading and trailing spaces. +static std::string_view Trim(std::string_view s) +{ + const size_t l_space = s.find_first_not_of(kSpace); + if( l_space > 0 ) + s.remove_prefix(l_space); + const size_t r_space = s.find_last_not_of(kSpace); + if( r_space != std::string_view::npos ) + s.remove_suffix(s.size() - r_space - 1); + return s; +} + +// Convert a line into our operation struct. +static Operation ParseSingleLine(std::string_view line) +{ + Operation op; + op.directive = Directive::kText; + op.arg = line; + + // Skip past leading space and '#'. + const size_t i = line.find_first_not_of(kSpace); + if( i == std::string_view::npos || line[i] != '#' ) + return op; + const size_t j = line.find_first_not_of(kSpace, i + 1); + if( j == std::string_view::npos ) + return op; + + // Extract directive and optional argument. + std::string_view directive(line.substr(j)); + std::string_view arg; + const size_t k = directive.find_first_of(kSpace); + if( k != std::string_view::npos ) + { + arg = Trim(directive.substr(k)); + directive.remove_suffix(directive.size() - k); + } + + if( directive == "define" ) + { + // If this is a macro with parameters or substitution value, we + // will copy the full directive (minus the leading and trailing + // space) to output on evaluation, so we will need to preserve + // the full line here. + if( arg.find_first_of(kSpaceOrLeftParen) != std::string_view::npos ) + { + op.directive = Directive::kRawDefine; + op.arg = Trim(line); + } + else + { + op.directive = Directive::kDefine; + op.arg = arg; + } + } + #define MATCH_DIRECTIVE(s, o) \ + else if( directive == s ) { op.directive = o; op.arg = arg; } + MATCH_DIRECTIVE("if", Directive::kIf) + MATCH_DIRECTIVE("elif", Directive::kElif) + MATCH_DIRECTIVE("else", Directive::kElse) + MATCH_DIRECTIVE("ifdef", Directive::kIfDef) + MATCH_DIRECTIVE("ifndef", Directive::kIfNDef) + MATCH_DIRECTIVE("endif", Directive::kEndIf) + MATCH_DIRECTIVE("undef", Directive::kUndef) + MATCH_DIRECTIVE("include", Directive::kInclude) + MATCH_DIRECTIVE("warning", Directive::kWarning) + MATCH_DIRECTIVE("error", Directive::kError) + #undef MATCH_DIRECTIVE + return op; +} + +// Convert lines to operations. +static std::vector<Operation> ParseLines( + const std::vector<std::string_view> &input_lines) +{ + std::vector<Operation> output; + output.reserve(input_lines.size()); + for(const auto &line : input_lines) + output.push_back(ParseSingleLine(line)); + return output; +} + +// Check for nonempty stack. +template <typename T> +static void AssertNonEmptyStack(const T &stack, const char *directive) +{ + if( stack.empty() ) + { + fprintf(stderr, "Unmatched %s\n", directive); + exit(EXIT_FAILURE); + } +} + +// Find branch locations. This makes skipping over conditional blocks +// much faster. This optimization probably doesn't make sense for +// typical code since most people aren't doing "#include __FILE__", +// but for our purposes it makes a big difference. +// +// Empirically, cppp's processing time is roughly linear to the number +// of "#include __FILE__" directives because it is able to jump to the +// relevant #if blocks quickly. Whereas GNU's cpp exhibits quadratic +// time because it always reads in the entire file for each #include. +static void IndexOps(std::vector<Operation> *code) +{ + // first = list of indices looking for #else destination. + // second = list of indices looking for #endif destination. + using StackFrame = std::pair<std::vector<size_t>, std::vector<size_t>>; + std::vector<StackFrame> stack; + for(size_t i = 0; i < code->size(); i++) + { + Operation *op = &((*code)[i]); + op->true_branch = op->false_branch = i + 1; + switch( op->directive ) + { + case Directive::kIf: + case Directive::kIfDef: + case Directive::kIfNDef: + // Start of conditional block. + stack.push_back(StackFrame()); + stack.back().first.push_back(i); + break; + + case Directive::kElif: + // End of one conditional block and start of the next block. + // Update previous false_branch destinations to point at the + // current conditional instruction. + AssertNonEmptyStack(stack, "#elif"); + for(size_t f : stack.back().first) + (*code)[f].false_branch = i; + stack.back().first.clear(); + stack.back().first.push_back(i); + break; + + case Directive::kElse: + // End of conditional block. Update previous false_branch + // destinations to skip past current instruction directly + // into the body of the conditional branch. + AssertNonEmptyStack(stack, "#else"); + for(size_t f : stack.back().first) + (*code)[f].false_branch = i + 1; + stack.back().first.clear(); + break; + + case Directive::kEndIf: + // End of conditional block. Update previous false_branch + // destinations to point at current instruction. + AssertNonEmptyStack(stack, "#endif"); + for(size_t f : stack.back().first) + (*code)[f].false_branch = i; + for(size_t f : stack.back().second) + (*code)[f].true_branch = (*code)[f].false_branch = i; + stack.pop_back(); + + [[fallthrough]]; + + case Directive::kDefine: + case Directive::kUndef: + case Directive::kInclude: + case Directive::kWarning: + case Directive::kRawDefine: + case Directive::kText: + // Other non-branching directives, including #endif. If + // we are currently inside a conditional block and the + // next instruction ends the block, we want to update the + // current instruction later to jump to the matching #endif. + // #if ... + // #if ... + // step 1 + // #endif // this will branch to #endif just before step 2 + // #else + // ... + // #endif + // step 2 + if( !stack.empty() && + i + 1 < code->size() && + ((*code)[i + 1].directive == Directive::kElif || + (*code)[i + 1].directive == Directive::kElse) ) + { + stack.back().second.push_back(i); + } + break; + + case Directive::kError: + // Error directives don't have any other place to go. + op->true_branch = op->false_branch = i; + break; + } + } +} + +// Try to evaluate a possible macro reference as integer. +static int LookupInt(const MacroTable &table, std::string_view token) +{ + std::unordered_set<std::string_view> used_macros; + for(MacroTable::const_iterator f = table.find(token); f != table.end();) + { + if( !used_macros.insert(token).second ) + { + fprintf(stderr, "Recursive macro reference: %s\n", + std::string(token).c_str()); + exit(EXIT_FAILURE); + } + token = f->second; + f = table.find(token); + } + int value; + if( sscanf(std::string(token).c_str(), "%d", &value) == 1 ) + return value; + return 0; +} + +// Evaluate a conditional expression. +static bool Evaluate(const MacroTable &table, std::string_view expr) +{ + // Try matching something like "a % b > c". + const std::string expr_string(expr); + std::array<char, 64> token[5]; + if( sscanf(expr_string.c_str(), "%s %s %s %s %s", + token[0].data(), + token[1].data(), + token[2].data(), + token[3].data(), + token[4].data()) == 5 ) + { + const int value1 = LookupInt(table, std::string_view(token[0].data())); + const std::string_view op1(token[1].data()); + const int value2 = LookupInt(table, std::string_view(token[2].data())); + const std::string_view op2(token[3].data()); + const int value3 = LookupInt(table, std::string_view(token[4].data())); + + #define INNER_EXPR(first_op, second_op) \ + if( op2 == #second_op ) \ + return value1 first_op value2 second_op value3 + #define OUTER_EXPR(first_op) \ + if( op1 == #first_op ) \ + { \ + INNER_EXPR(first_op, ==); \ + INNER_EXPR(first_op, !=); \ + INNER_EXPR(first_op, <); \ + INNER_EXPR(first_op, >); \ + INNER_EXPR(first_op, <=); \ + INNER_EXPR(first_op, >=); \ + } + OUTER_EXPR(+) else + OUTER_EXPR(-) else + OUTER_EXPR(*) else + OUTER_EXPR(/) else + OUTER_EXPR(%) else + OUTER_EXPR(<<) else + OUTER_EXPR(>>) + #undef OUTER_EXPR + #undef INNER_EXPR + } + + // Try matching something like "a > b"; + if( sscanf(expr_string.c_str(), "%s %s %s", + token[0].data(), + token[1].data(), + token[2].data()) == 3 ) + { + const int lhs = LookupInt(table, std::string_view(token[0].data())); + const std::string_view op(token[1].data()); + const int rhs = LookupInt(table, std::string_view(token[2].data())); + #define EXPR(o) if( op == #o ) return lhs o rhs + EXPR(==); + EXPR(!=); + EXPR(<); + EXPR(>); + EXPR(<=); + EXPR(>=); + #undef EXPR + } + + // Check if there are multiple tokens in this expression. If so, + // since it didn't match one of the earlier multi-token branches, + // it's an expression that we don't support. + // + // Also check if there are operators in this expression. This is + // a best effort attempt to issue warnings for single-token + // expressions like "x>0" (as opposed to "x > 0"), instead of + // silently evaluating them to zero. + if( expr.find_first_of(kSpace) != std::string_view::npos || + expr.find_first_of("+-*/%^~!&|<>()") != std::string_view::npos ) + { + fprintf(stderr, "Expression not supported by this preprocessor:\n%s\n", + std::string(expr).c_str()); + exit(EXIT_FAILURE); + } + + // Assume single value expression. + return LookupInt(table, expr) != 0; +} + +// Execute preprocessor instructions. +static void Run(int depth, + const std::vector<Operation> &code, + MacroTable *macros, + Stats *stats) +{ + stats->include_count++; + if( stats->max_include_depth < depth ) + { + if( depth > kMaxIncludeDepth ) + { + fprintf(stderr, "Include stack too deep: %d\n", depth); + exit(EXIT_FAILURE); + } + stats->max_include_depth = depth; + } + + for(size_t i = 0; i < code.size();) + { + stats->operation_steps++; + + const Operation &op = code[i]; + i = op.true_branch; + switch( op.directive ) + { + case Directive::kIf: + case Directive::kElif: + if( !Evaluate(*macros, op.arg) ) + i = op.false_branch; + break; + + case Directive::kIfDef: + if( macros->find(op.arg) == macros->end() ) + i = op.false_branch; + break; + + case Directive::kIfNDef: + if( macros->find(op.arg) != macros->end() ) + i = op.false_branch; + break; + + case Directive::kElse: + case Directive::kEndIf: + break; + + case Directive::kDefine: + (*macros)[op.arg] = ""; + break; + + case Directive::kRawDefine: + { + const size_t j = op.arg.find_first_of(kSpace); + const size_t k = op.arg.find_first_not_of(kSpace, j + 1); + const size_t l = op.arg.find_first_of(kSpaceOrLeftParen, k + 1); + const std::string_view macro_name = op.arg.substr(k, l - k); + if( op.arg[l] == '(' ) + { + // Macro with parameters. Since we don't do any macro + // expansion, there is no way to expand the value + // correctly, so we will mark the macro as defined but + // don't bother with putting the value in our table. + // + // That said, we will mark the macro as having *some* + // value, so we will copy #undef directives when we + // encounter those. + (*macros)[macro_name] = op.arg; + } + else + { + // Marco without parameters, but with a value. Here we + // have a chance of making some substitutions work, like + // these kind of things: + // + // #define X __FILE__ + // #define Y X + // #include Y + // + // So we will record the value in our table. + const size_t value = op.arg.find_first_not_of(kSpace, l); + if( value != std::string_view::npos ) + (*macros)[macro_name] = Trim(op.arg.substr(value)); + else + (*macros)[macro_name] = ""; + } + } + + // Copy the whole macro directive to output, so that the next + // preprocessor might have some chance to make use of it. + fwrite(op.arg.data(), op.arg.size(), 1, stdout); + fputc('\n', stdout); + break; + + case Directive::kUndef: + if( const MacroTable::iterator f = macros->find(op.arg); + f != macros->end() ) + { + // If a macro has value, then we also want to include the + // #undef statement in the output, otherwise a subsequent + // #define for the same macro name might not work. + if( !(f->second.empty()) ) + { + fputs("#undef ", stdout); + fwrite(op.arg.data(), op.arg.size(), 1, stdout); + fputc('\n', stdout); + } + macros->erase(f); + } + break; + + case Directive::kInclude: + { + std::string_view include_file = op.arg; + std::unordered_set<std::string_view> used_macros; + for(auto f = macros->find(include_file); f != macros->end();) + { + if( !used_macros.insert(include_file).second ) + { + fprintf(stderr, "Recursive macro reference: %s\n", + std::string(include_file).c_str()); + exit(EXIT_FAILURE); + } + include_file = f->second; + f = macros->find(include_file); + } + if( include_file == "__FILE__" ) + { + Run(depth + 1, code, macros, stats); + } + else + { + fputs("#include ", stdout); + fwrite(op.arg.data(), op.arg.size(), 1, stdout); + fputc('\n', stdout); + } + } + break; + + case Directive::kWarning: + fwrite(op.arg.data(), op.arg.size(), 1, stderr); + fputc('\n', stderr); + break; + + case Directive::kError: + fwrite(op.arg.data(), op.arg.size(), 1, stderr); + fputc('\n', stderr); + exit(EXIT_FAILURE); + break; + + case Directive::kText: + fwrite(op.arg.data(), op.arg.size(), 1, stdout); + break; + } + } +} + +} // namespace + +int main(int argc, char **argv) +{ + // Initialize macros and load input. + MacroTable macros; + std::string input_text; + int input_file_count = 0; + for(int i = 1; i < argc; i++) + { + if( argv[i][0] == '-' && argv[i][1] == 'D' ) + { + const std::string_view d(argv[i] + 2); + const size_t e = d.find('='); + if( e != std::string_view::npos ) + macros[d.substr(0, e)] = d.substr(e + 1); + else + macros[d] = ""; + } + else + { + if( !LoadInput(argv[i], &input_text) ) + return 1; + input_file_count++; + } + } + + // If no input is specified, try reading from stdin. + if( input_file_count == 0 ) + LoadInputFromHandle(stdin, &input_text); + + // Parse lines. + std::vector<Operation> code = ParseLines(TokenizeToLines(&input_text)); + IndexOps(&code); + + // Execute preprocessor. + Stats stats; + Run(0, code, ¯os, &stats); + printf("# /* include_count = %" PRId64 " */\n", stats.include_count); + printf("# /* operation_steps = %" PRId64 " */\n", stats.operation_steps); + printf("# /* max_include_depth = %d */\n", stats.max_include_depth); + return 0; +} diff --git a/ioccc/2020/yang/hint.text b/ioccc/2020/yang/hint.text new file mode 100644 index 0000000000000000000000000000000000000000..e4dd1316a1f1a36901e1b443ed874f766df44d9b --- /dev/null +++ b/ioccc/2020/yang/hint.text @@ -0,0 +1,141 @@ +# Best abuse of CPP + +Don Yang +<http://uguu.org/> + + +The code for this entry can be found in prog.c + +## Judges' comments: +### To use: + + make + ./prog + +### Try: + + echo "International Obfuscated C Code Contest 2020" | ./prog 23209 > code.c + + # compile without a PIN + cc code.c -o decode + # yes, you must compile with -DPIN=<number> + + # compile with the wrong pin + cc -DPIN=555 code.c -o wrongcoded # wait for it ... + ./wrongcoded | hexdump -C + # Use the wrong PIN: You're gonna have a bad time. + + # compile with a PIN + cc -DPIN=23209 code.c -o decoded # wait for it ... + ./decoded + # weeeeeeeeeeeeee! You are having a good time! + +### Selected Judges Remarks: + +You might think of this entry as code obfuscater with a code. +If you use the wrong code, you're gonna have a bad time. +What is compiling this entry about? +[Having a good .. time](https://southpark.fandom.com/wiki/Asspen/Script)! + +This winning entry also comes with a [JavaScript timelapse +spoiler](spoiler.html) that shows how this entry was written. + + +## Author's comments: +### Synopsis + + echo "Hello world" | ./mile 12345 > encoded.c + + gcc -DPIN=12345 encoded.c -o ./decoded && ./decoded + +### Details + +Mile is a C code generator. Run without arguments for the help message below: + + usage: [PIN] < input.txt > output.c + + where [PIN] is an integer in the range of 1..65535 + +When run with an encoding PIN (first command line argument), Mile will +read bytes from stdin and generate C code on stdout. Example: + + echo "Hello, world!" | ./mile 56789 > encoded.c + +This generated code will reproduce the same input bytes on stdout when +executed, if it was compiled with the same encoding PIN. + + gcc -DPIN=56789 encode.c -o decoded + +The generated code reconstructs all data at compile time by seeding a +random number generator with the given PIN to reproduce the input bytes, +and simply does one fwrite() call at run time to print those bytes. Not +specifying a PIN is a compile time error. Specify the wrong PIN and +output code will still compile, but will likely produce garbage instead of +the input bytes. If the original input was empty then any PIN works, but +you might get a compile time warning complaining about empty arrays. + +Because all data is reconstructed at compile time, expect the compile time +to be excruciatingly long if you try to encode too much data. Code +generated by encoding a haiku will probably compile in seconds, a limerick +may require tens of seconds, a sonnet will take minutes. Give Mile an +epic poem and you can probably write a faster preprocessor before GCC is +done (Clang probably already failed long before then). + +I see that there is a lack of preprocessor abuse in recent years, probably +because programming in preprocessor is too tedious. Mile is meant to help +with that by producing C code filled with at least 98% preprocessor lines +for any input. Now you too can enjoy long compile times with minimal +effort. + +### Features + ++ Output is randomized using system clock, so if you wait a second between + runs, you should get a different generated code even for the same + encoding PIN. + ++ Customized bytecode encoding of preprocessor boilerplates, mostly for + compression but should also make reverse engineering more fun. + ++ CRC32 of the source code is embedded in the source code itself. + ++ Code layout shaped to resemble "Mile" from "Didn't I Say to Make My + Abilities Average in the Next Life?!". Mile is known to be able to talk + to nanomachines directly, which is exactly what programming in + preprocessor feels like. + +### Compatibility + +Mile has been verified to work in these environments (also, compiles +without warnings on all of these): + ++ gcc 9.2.0 on Cygwin ++ gcc 8.3.0 on Linux ++ gcc 7.4.0 on Cygwin ++ gcc 6.1.0 on JSLinux ++ gcc 5.4.0 on Linux ++ clang 8.0.1 on Linux ++ clang 8.0.1 on Cygwin ++ tcc 0.9.27 on Linux ++ tcc 0.9.25 on JSLinux + +Output of Mile is a bit more taxing, and only works with a subset of the +above: + ++ gcc: works just fine when using 8.3.0 and below, but may trigger warning + for large files. gcc 9.2.0 and above may crash with large files. ++ clang: works fine for small files, fails on large files due to + [preprocessor bug](https://bugs.llvm.org/show_bug.cgi?id=44480). ++ tcc: works just fine on Linux. Fails silently on JSLinux. + +For people eager to encode large files, an extra utility has been packaged +with this entry to preprocess the generated output to make them more +acceptable to typical compilers. View the [cppp.cc](cppp.cc) source and +then compile it with a c++ compiler of your choice. + +----------------------------------------------------------------------------------------------------- +(c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc]. + +[judges]: http://www.ioccc.org/judges.html +[cc]: http://creativecommons.org/licenses/by-sa/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/ioccc/2020/yang/prog.c b/ioccc/2020/yang/prog.c new file mode 100644 index 0000000000000000000000000000000000000000..cc78a16a7d91c803f425bdbaff9f9ebba9aafc59 --- /dev/null +++ b/ioccc/2020/yang/prog.c @@ -0,0 +1,37 @@ + #\ + define C(c /**/)#c + /*size=3173*/#include<stdio.h> + /*crc=b7f9ecff.*/#include<stdlib.h> + /*Mile/Adele_von_Ascham*/#include<time.h> + typedef/**/int(I);I/*:3*/d,i,j,a,b,l,u[16],v + [18],w[36],x,y,z,k;char*P="\n\40(),",*p,*q,*t[18],m[4]; + void/**/O(char*q){for(;*q;q++)*q>32?z=111-*q?z=(z+*q)%185,(k? + k--:(y=z%37,(x=z/37%7)?printf(*t,t[x],y?w[y-1]:95):y>14&&y<33?x + =y>15,printf(t[15+x],x?2<<y%16:l,x?(1<<y%16)-1:1):puts(t[y%28]))) + ,0:z+82:0;}void/**/Q(I(p),I*q){for(x=0;x<p;x++){q[x]=x;}for(;--p + >1;q[p]=y)y =q[x=rand()%-~p],q[x]=q[p];}char/**/n[999]=C(Average?!nQVQd%R>Rd% + R% %RNIPRfi#VQ}R;TtuodtsRUd%RUd%RUOSetirwf!RnruterR{RTSniamRtniQ>h.oidts<edulc + ni #V>rebmun<=NIPD-RhtiwRelipmocResaelPRrorre#QNIPRfednfi#V__ELIF__R_ +Re nifed#V~-VU0V;}V{R= R][ORrahcRdengisnuRtsnocRcitatsVesle#Vfidne#V53556 + . .1RfoRegnarRehtRniRre getniRnaRsiR]NIP[R erehwQQc.tuptuoR>Rtxt.tupniR + < R]NIP[R:egasuV_Redulcn i#VfednfiVfednuVenife dVfedfiVQc%Rs%#V);I/**/main( + I( f),char**e){if(f){for(i= time(NULL),p=n,q= n+998,x=18;x;p++){*p>32&&!( + *--q=*p>80&&*p<87?P[*p- 81]:* p)?t [( -- x)]=q+1:q;}if(f-2||(d=atoi + (e[1]))<1||65536<d){;O(" \""); goto O;}srand(i);Q(16,u);i=0;Q( + 36,w);for(;i<36; i++){w[i] +=w [i]<26 ? 97:39; }O(C(ouoo9oBotoo%]# + ox^#oy_#ozoou#o{ a#o|b#o}c# o~d#oo-e #oo. f#oo/g#oo0h#oo1i#oo + 2j#oo3k#oo4l#o p));for(j =8;EOF -(i= getchar());l+=1){a=1+ + rand()%16;for(b =0;b<a||i- main (0,e);b++)x=d^d/4^d/8^d/ + 32,d= (d/ 2|x<<15)&65535; b|= !l<<17;Q(18,v);for(a=0;a<18; + a++ ){if( (b&(1<<(i=v[a] ))))* m=75+i,O(m),j=i<17&&j<i?i:j;}O(C( + !) ); }O(C(oqovoo97o /n!));i= 0;for(;i<8;O(m))m[2]=35,*m=56+u[i],m[1 + ]= 75 +i++;O(C(oA!oro oqoo9) );k=112-j*7;O(C(6o.!Z!Z#5o-!Y!Y#4~!X!X#3} + !W !W #2 |!V!V#1{!U!U#0z! T!T#/y!S!S#.x!R!R#-w!Q!Q#ooAv!P!P#+o#!O!O#*t!N! + N# oo >s!M!M#oo=r!L!L#oo<q!K!K# &pIo@:;= oUm#oo98m##oo9=8m#oo9oUm###oo9;=8m#o + o9 oUm##oo9=oUm#oo98m#### o09] #o1:^#o2;_#o3<o ou#o4=a#o5>b#o6?c#o + 7@d#o8A e#o 9B f#o:Cg#o; D h#o<Ei #o=Fj#o> Gk#o?Hl#oo9os##### + ));d=0 ;} O: for(x=y=0;x<8;++ + x)y|= d&(1<<u[x])? + 1<< x:0;return + /* :9 */ + y ; } diff --git a/ioccc/COPYING b/ioccc/COPYING new file mode 100644 index 0000000000000000000000000000000000000000..604209a804632b6e5274005a22293976d07c3099 --- /dev/null +++ b/ioccc/COPYING @@ -0,0 +1,359 @@ +Creative Commons Legal Code + +Attribution-ShareAlike 3.0 Unported + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR + DAMAGES RESULTING FROM ITS USE. + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE +COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY +COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS +AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY +BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS +CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND +CONDITIONS. + +1. Definitions + + a. "Adaptation" means a work based upon the Work, or upon the Work and + other pre-existing works, such as a translation, adaptation, + derivative work, arrangement of music or other alterations of a + literary or artistic work, or phonogram or performance and includes + cinematographic adaptations or any other form in which the Work may be + recast, transformed, or adapted including in any form recognizably + derived from the original, except that a work that constitutes a + Collection will not be considered an Adaptation for the purpose of + this License. For the avoidance of doubt, where the Work is a musical + work, performance or phonogram, the synchronization of the Work in + timed-relation with a moving image ("synching") will be considered an + Adaptation for the purpose of this License. + b. "Collection" means a collection of literary or artistic works, such as + encyclopedias and anthologies, or performances, phonograms or + broadcasts, or other works or subject matter other than works listed + in Section 1(f) below, which, by reason of the selection and + arrangement of their contents, constitute intellectual creations, in + which the Work is included in its entirety in unmodified form along + with one or more other contributions, each constituting separate and + independent works in themselves, which together are assembled into a + collective whole. A work that constitutes a Collection will not be + considered an Adaptation (as defined below) for the purposes of this + License. + c. "Creative Commons Compatible License" means a license that is listed + at https://creativecommons.org/compatiblelicenses that has been + approved by Creative Commons as being essentially equivalent to this + License, including, at a minimum, because that license: (i) contains + terms that have the same purpose, meaning and effect as the License + Elements of this License; and, (ii) explicitly permits the relicensing + of adaptations of works made available under that license under this + License or a Creative Commons jurisdiction license with the same + License Elements as this License. + d. "Distribute" means to make available to the public the original and + copies of the Work or Adaptation, as appropriate, through sale or + other transfer of ownership. + e. "License Elements" means the following high-level license attributes + as selected by Licensor and indicated in the title of this License: + Attribution, ShareAlike. + f. "Licensor" means the individual, individuals, entity or entities that + offer(s) the Work under the terms of this License. + g. "Original Author" means, in the case of a literary or artistic work, + the individual, individuals, entity or entities who created the Work + or if no individual or entity can be identified, the publisher; and in + addition (i) in the case of a performance the actors, singers, + musicians, dancers, and other persons who act, sing, deliver, declaim, + play in, interpret or otherwise perform literary or artistic works or + expressions of folklore; (ii) in the case of a phonogram the producer + being the person or legal entity who first fixes the sounds of a + performance or other sounds; and, (iii) in the case of broadcasts, the + organization that transmits the broadcast. + h. "Work" means the literary and/or artistic work offered under the terms + of this License including without limitation any production in the + literary, scientific and artistic domain, whatever may be the mode or + form of its expression including digital form, such as a book, + pamphlet and other writing; a lecture, address, sermon or other work + of the same nature; a dramatic or dramatico-musical work; a + choreographic work or entertainment in dumb show; a musical + composition with or without words; a cinematographic work to which are + assimilated works expressed by a process analogous to cinematography; + a work of drawing, painting, architecture, sculpture, engraving or + lithography; a photographic work to which are assimilated works + expressed by a process analogous to photography; a work of applied + art; an illustration, map, plan, sketch or three-dimensional work + relative to geography, topography, architecture or science; a + performance; a broadcast; a phonogram; a compilation of data to the + extent it is protected as a copyrightable work; or a work performed by + a variety or circus performer to the extent it is not otherwise + considered a literary or artistic work. + i. "You" means an individual or entity exercising rights under this + License who has not previously violated the terms of this License with + respect to the Work, or who has received express permission from the + Licensor to exercise rights under this License despite a previous + violation. + j. "Publicly Perform" means to perform public recitations of the Work and + to communicate to the public those public recitations, by any means or + process, including by wire or wireless means or public digital + performances; to make available to the public Works in such a way that + members of the public may access these Works from a place and at a + place individually chosen by them; to perform the Work to the public + by any means or process and the communication to the public of the + performances of the Work, including by public digital performance; to + broadcast and rebroadcast the Work by any means including signs, + sounds or images. + k. "Reproduce" means to make copies of the Work by any means including + without limitation by sound or visual recordings and the right of + fixation and reproducing fixations of the Work, including storage of a + protected performance or phonogram in digital form or other electronic + medium. + +2. Fair Dealing Rights. Nothing in this License is intended to reduce, +limit, or restrict any uses free from copyright or rights arising from +limitations or exceptions that are provided for in connection with the +copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, +Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +perpetual (for the duration of the applicable copyright) license to +exercise the rights in the Work as stated below: + + a. to Reproduce the Work, to incorporate the Work into one or more + Collections, and to Reproduce the Work as incorporated in the + Collections; + b. to create and Reproduce Adaptations provided that any such Adaptation, + including any translation in any medium, takes reasonable steps to + clearly label, demarcate or otherwise identify that changes were made + to the original Work. For example, a translation could be marked "The + original work was translated from English to Spanish," or a + modification could indicate "The original work has been modified."; + c. to Distribute and Publicly Perform the Work including as incorporated + in Collections; and, + d. to Distribute and Publicly Perform Adaptations. + e. For the avoidance of doubt: + + i. Non-waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme cannot be waived, the Licensor + reserves the exclusive right to collect such royalties for any + exercise by You of the rights granted under this License; + ii. Waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme can be waived, the Licensor waives the + exclusive right to collect such royalties for any exercise by You + of the rights granted under this License; and, + iii. Voluntary License Schemes. The Licensor waives the right to + collect royalties, whether individually or, in the event that the + Licensor is a member of a collecting society that administers + voluntary licensing schemes, via that society, from any exercise + by You of the rights granted under this License. + +The above rights may be exercised in all media and formats whether now +known or hereafter devised. The above rights include the right to make +such modifications as are technically necessary to exercise the rights in +other media and formats. Subject to Section 8(f), all rights not expressly +granted by Licensor are hereby reserved. + +4. Restrictions. The license granted in Section 3 above is expressly made +subject to and limited by the following restrictions: + + a. You may Distribute or Publicly Perform the Work only under the terms + of this License. You must include a copy of, or the Uniform Resource + Identifier (URI) for, this License with every copy of the Work You + Distribute or Publicly Perform. You may not offer or impose any terms + on the Work that restrict the terms of this License or the ability of + the recipient of the Work to exercise the rights granted to that + recipient under the terms of the License. You may not sublicense the + Work. You must keep intact all notices that refer to this License and + to the disclaimer of warranties with every copy of the Work You + Distribute or Publicly Perform. When You Distribute or Publicly + Perform the Work, You may not impose any effective technological + measures on the Work that restrict the ability of a recipient of the + Work from You to exercise the rights granted to that recipient under + the terms of the License. This Section 4(a) applies to the Work as + incorporated in a Collection, but this does not require the Collection + apart from the Work itself to be made subject to the terms of this + License. If You create a Collection, upon notice from any Licensor You + must, to the extent practicable, remove from the Collection any credit + as required by Section 4(c), as requested. If You create an + Adaptation, upon notice from any Licensor You must, to the extent + practicable, remove from the Adaptation any credit as required by + Section 4(c), as requested. + b. You may Distribute or Publicly Perform an Adaptation only under the + terms of: (i) this License; (ii) a later version of this License with + the same License Elements as this License; (iii) a Creative Commons + jurisdiction license (either this or a later license version) that + contains the same License Elements as this License (e.g., + Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible + License. If you license the Adaptation under one of the licenses + mentioned in (iv), you must comply with the terms of that license. If + you license the Adaptation under the terms of any of the licenses + mentioned in (i), (ii) or (iii) (the "Applicable License"), you must + comply with the terms of the Applicable License generally and the + following provisions: (I) You must include a copy of, or the URI for, + the Applicable License with every copy of each Adaptation You + Distribute or Publicly Perform; (II) You may not offer or impose any + terms on the Adaptation that restrict the terms of the Applicable + License or the ability of the recipient of the Adaptation to exercise + the rights granted to that recipient under the terms of the Applicable + License; (III) You must keep intact all notices that refer to the + Applicable License and to the disclaimer of warranties with every copy + of the Work as included in the Adaptation You Distribute or Publicly + Perform; (IV) when You Distribute or Publicly Perform the Adaptation, + You may not impose any effective technological measures on the + Adaptation that restrict the ability of a recipient of the Adaptation + from You to exercise the rights granted to that recipient under the + terms of the Applicable License. This Section 4(b) applies to the + Adaptation as incorporated in a Collection, but this does not require + the Collection apart from the Adaptation itself to be made subject to + the terms of the Applicable License. + c. If You Distribute, or Publicly Perform the Work or any Adaptations or + Collections, You must, unless a request has been made pursuant to + Section 4(a), keep intact all copyright notices for the Work and + provide, reasonable to the medium or means You are utilizing: (i) the + name of the Original Author (or pseudonym, if applicable) if supplied, + and/or if the Original Author and/or Licensor designate another party + or parties (e.g., a sponsor institute, publishing entity, journal) for + attribution ("Attribution Parties") in Licensor's copyright notice, + terms of service or by other reasonable means, the name of such party + or parties; (ii) the title of the Work if supplied; (iii) to the + extent reasonably practicable, the URI, if any, that Licensor + specifies to be associated with the Work, unless such URI does not + refer to the copyright notice or licensing information for the Work; + and (iv) , consistent with Ssection 3(b), in the case of an + Adaptation, a credit identifying the use of the Work in the Adaptation + (e.g., "French translation of the Work by Original Author," or + "Screenplay based on original Work by Original Author"). The credit + required by this Section 4(c) may be implemented in any reasonable + manner; provided, however, that in the case of a Adaptation or + Collection, at a minimum such credit will appear, if a credit for all + contributing authors of the Adaptation or Collection appears, then as + part of these credits and in a manner at least as prominent as the + credits for the other contributing authors. For the avoidance of + doubt, You may only use the credit required by this Section for the + purpose of attribution in the manner set out above and, by exercising + Your rights under this License, You may not implicitly or explicitly + assert or imply any connection with, sponsorship or endorsement by the + Original Author, Licensor and/or Attribution Parties, as appropriate, + of You or Your use of the Work, without the separate, express prior + written permission of the Original Author, Licensor and/or Attribution + Parties. + d. Except as otherwise agreed in writing by the Licensor or as may be + otherwise permitted by applicable law, if You Reproduce, Distribute or + Publicly Perform the Work either by itself or as part of any + Adaptations or Collections, You must not distort, mutilate, modify or + take other derogatory action in relation to the Work which would be + prejudicial to the Original Author's honor or reputation. Licensor + agrees that in those jurisdictions (e.g. Japan), in which any exercise + of the right granted in Section 3(b) of this License (the right to + make Adaptations) would be deemed to be a distortion, mutilation, + modification or other derogatory action prejudicial to the Original + Author's honor and reputation, the Licensor will waive or not assert, + as appropriate, this Section, to the fullest extent permitted by the + applicable national law, to enable You to reasonably exercise Your + right under Section 3(b) of this License (right to make Adaptations) + but not otherwise. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR +OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY +KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, +INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, +FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF +LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, +WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION +OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE +LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR +ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES +ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + + a. This License and the rights granted hereunder will terminate + automatically upon any breach by You of the terms of this License. + Individuals or entities who have received Adaptations or Collections + from You under this License, however, will not have their licenses + terminated provided such individuals or entities remain in full + compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will + survive any termination of this License. + b. Subject to the above terms and conditions, the license granted here is + perpetual (for the duration of the applicable copyright in the Work). + Notwithstanding the above, Licensor reserves the right to release the + Work under different license terms or to stop distributing the Work at + any time; provided, however that any such election will not serve to + withdraw this License (or any other license that has been, or is + required to be, granted under the terms of this License), and this + License will continue in full force and effect unless terminated as + stated above. + +8. Miscellaneous + + a. Each time You Distribute or Publicly Perform the Work or a Collection, + the Licensor offers to the recipient a license to the Work on the same + terms and conditions as the license granted to You under this License. + b. Each time You Distribute or Publicly Perform an Adaptation, Licensor + offers to the recipient a license to the original Work on the same + terms and conditions as the license granted to You under this License. + c. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this License, and without further action + by the parties to this agreement, such provision shall be reformed to + the minimum extent necessary to make such provision valid and + enforceable. + d. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in writing + and signed by the party to be charged with such waiver or consent. + e. This License constitutes the entire agreement between the parties with + respect to the Work licensed here. There are no understandings, + agreements or representations with respect to the Work not specified + here. Licensor shall not be bound by any additional provisions that + may appear in any communication from You. This License may not be + modified without the mutual written agreement of the Licensor and You. + f. The rights granted under, and the subject matter referenced, in this + License were drafted utilizing the terminology of the Berne Convention + for the Protection of Literary and Artistic Works (as amended on + September 28, 1979), the Rome Convention of 1961, the WIPO Copyright + Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 + and the Universal Copyright Convention (as revised on July 24, 1971). + These rights and subject matter take effect in the relevant + jurisdiction in which the License terms are sought to be enforced + according to the corresponding provisions of the implementation of + those treaty provisions in the applicable national law. If the + standard suite of rights granted under applicable copyright law + includes additional rights not granted under this License, such + additional rights are deemed to be included in the License; this + License is not intended to restrict the license of any rights under + applicable law. + + +Creative Commons Notice + + Creative Commons is not a party to this License, and makes no warranty + whatsoever in connection with the Work. Creative Commons will not be + liable to You or any party on any legal theory for any damages + whatsoever, including without limitation any general, special, + incidental or consequential damages arising in connection to this + license. Notwithstanding the foregoing two (2) sentences, if Creative + Commons has expressly identified itself as the Licensor hereunder, it + shall have all rights and obligations of Licensor. + + Except for the limited purpose of indicating to the public that the + Work is licensed under the CCPL, Creative Commons does not authorize + the use by either party of the trademark "Creative Commons" or any + related trademark or logo of Creative Commons without the prior + written consent of Creative Commons. Any permitted use will be in + compliance with Creative Commons' then-current trademark usage + guidelines, as may be published on its website or otherwise made + available upon request from time to time. For the avoidance of doubt, + this trademark restriction does not form part of the License. + + Creative Commons may be contacted at https://creativecommons.org/.