ÎÌÌÌ̈ˆˆ¬ªªª¬ˆˆˆ¬ÌÌ̬ÌÀ̬ÌÀ̬ÌÀÌÌÌìÌÀÀî̬ÀÌÀ¬ÀÀÀ¬ÀÀÀ¬ÀÀÎÌÌÌ̈ˆˆ¬ªªª¬ˆˆˆ¬ÌÌ̬ÌÌ̬ÌÀ̬ÌÀÌÌÌìÌÀÀî̬ÀÌ̬ÀÀÀ¬ÀÀÀ¬ÀÀ¬ÌÌ̬ªªª¬ª¬ª¬ªÊ̬ªªªŒˆˆˆÌÀÌÎÌÌÎ̬̪ªÀ쬪ÀÀÀÌîÀìîÌÌîî¬ÌÌ̬ªªª¬ª¬ª¬ªÊ̬ªªªŒˆˆˆÌÀÌÎÌÌÎ̬̪ªÀ쬪ÀÀÀÌîÀìîÌÌîî >À?qwqqwÑÝÑÑÝÑÝÝÑÝÝÑÝÝÑÝÝqwwqwwÝÝÝÝÝÑÝÝ×ÝÝÑÝÝqwf-""-""-ÝÝ-""'bf&r"ÝÝ-""-""qw""-""'bffÑ"""ÒÑ"""ÒÑ"ÝÝÝÑ"""Òq"fffaf"fÖÝ-""ÒÑ"""ÒÑ'""ÒÑ"""Òq"bff-""""-""""-"ÝÝ--""""''fff&&hffÝ""""-""""-""""-""""''hff-""""-""""-"ÒÝ"-""""'‚fff&‚hff-""""-""""ÝÝ"""-""""'‚ˆf&-""""-""""-""""-""""'ˆhff&ˆhff-""""}""""ÝÝ-""-""""'ˆˆˆ(-""""-""""-""""-""""wˆˆhfwˆˆfv-""""w'"""ÝÝ-""-""""wˆˆˆx-""""-""""-""""-""""'ˆˆˆ('ˆxˆ(-""""}""""ÝÝ-""-""""'ˆˆˆ(-""""-""""-""""-""""'‚ˆˆ"'‚w‡"-""""-""""ÝÝ"""-""""'‚ˆˆ"Ñ"""ÝÝ-""ÝÝ-""ww'""ww'ˆ(ÝÝ-x(ÝÝ-""ww'""ww'""ÝÝ-""ÝÝ-ˆ(ÝÝ-"Ò""Ò"Ò""Ò"r"'r"r"'rrÒ""ÒrÒ""Ò"f&'r"r"'v"ÒˆˆØ"ÒˆˆØrÒˆˆØÑÝ-"""Ý-r""Ý'"""×'f&"w-"""}-"""mff""×'"bf׈ˆˆÝˆˆˆ}ˆˆˆÑ""""Ò"w'"rr‚ˆrrbffrÒ""""Ò""""bffˆrrr‚ˆvÒˆ8ƒˆØˆ8ƒˆØˆ8ƒˆØÑ""""Ò"r""r"ˆˆ(rbff(Ò""""Ò""""bffˆ(r"ˆˆfÖˆ3ƒˆØˆ3ƒˆØˆ3ƒˆØÑ""""Ò""""r‚ˆˆˆrbffˆÒ""""Ò""""rf†ˆˆr‚ˆhffˆ8ƒˆØˆ8ƒˆØˆ8ƒˆØÑ""""Ò""""r‡ˆˆˆw‡f†ˆ×""""Ò""""r‡ˆˆˆw‡ˆhffˆ8ƒˆØˆ8ƒˆØˆ8ƒˆØÑ""""Ò""""r‚ˆˆˆr‚ˆˆˆÒ""""Òw'""r‚ˆˆˆr‚ˆhffˆ33ˆØˆ33ˆØˆ33ˆØÑ""""Ò""""r"ˆˆ(r"ˆˆ(Ò""""rww""r"ˆˆ(r"ˆˆfÖˆˆˆˆØˆˆˆˆØˆˆˆˆØÑÝÝ""ÒÝÝ""ÒÝÝ‚ˆÒÝÝ‚ˆÒÝÝ""Ò}ww"ÒÝÝ‚ˆÒÝÝ‚ˆÒÝ݈ˆØÝ݈ˆØÝ݈ˆˆ-""-"-""-"-""-'-""-'-""-"-rww"-""-'ˆˆ-'ˆˆˆˆˆˆˆˆˆØÑ"""ÒÝ"""ÒÝ"""Ò×"""Ò×"""ÒÝ""w×Ý"""Ò׈ˆˆØ×ˆˆˆØÝˆˆˆØÝˆˆˆØÝ-""""-""""-""""-""""-""""-""""-""""HD„ˆˆ3ˆˆˆˆˆˆˆˆˆˆ-""""-""""-""""-""""-""""-""""-""""ˆˆDˆ83ˆˆˆˆˆˆˆˆˆˆ-""""-""""-""""-""""-""""-""""-""""ˆD„ˆˆ3ˆˆˆˆˆˆˆˆˆˆ-""""-""""-""""-""""-""""-""""-""""H„ˆˆˆ3ˆˆˆˆˆˆˆˆˆˆ-ÒÝ""-""""-""""-""""-""""-""""-""""HDDˆ83ƒˆˆˆˆˆˆˆˆˆ-ÝÝ-"-""""-""""-""""-""""-""""-""""ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÑÝÝ-ww'""ÝÝ-""ÝÝ-""ÝÝ-""ÝÝ-"fvw'""Ý݈ˆÝ݈ˆÝ݈ˆÝ݈ˆÝÝÝÝ}"'r"Ò""Ò"Ò""Ò"Ò""×"Ò""Òbff'r"ÒˆˆØˆØˆˆØˆØˆˆØˆØˆˆØˆØˆˆØÑÝ'"""×-"""Ý-"""Ý-"rwÝ-"""mff""׈ˆˆÝˆˆˆÝˆˆˆÝˆˆˆÝˆˆˆqr‚ˆrÒ""""Ò""""Ò"""'Ò""""bffˆrÒˆDDˆØˆˆˆˆØˆˆˆˆØˆˆˆˆØˆˆˆˆØq"ˆˆ(Ò""""Ò""""Ò""""Òrw""rf†ˆ(ÒˆˆH„؈ˆˆˆØˆˆˆˆØˆˆˆˆØˆˆˆˆØq‚ˆˆˆÒ""""Ò""""Ò""""Òww'"r‚ˆˆˆÒˆHDˆØˆˆˆˆØˆˆˆˆØˆˆˆˆØˆˆˆˆØq‡ˆˆˆ×""""Ò""""Ò""""Òww'"r‡w‡ˆÝˆDˆˆØˆˆˆˆØˆˆˆˆØˆˆˆˆØˆˆˆˆØq‚ˆˆˆÒ""""Ò""""Ò""""Òww'"rrwwØÝˆDD„؈ˆˆˆØˆˆˆˆØˆˆˆˆØˆˆˆˆØq"ˆˆ(Ò""""Ò""""Ò""""Òrw""rrww(݈ˆˆˆØˆˆˆˆØˆˆˆˆØˆˆˆˆØˆˆˆˆØÑÝÝ‚ˆÒÝÝ""ÒÝÝ""ÒÝÝ""rww""ÒÝ}wwrgfˆˆØÝ݈ˆØÝ݈ˆØÝ݈ˆØÝ݈ˆˆ-""-'-""-"-""-"-""-"'r"'"-""w''ff†ˆˆˆˆˆˆˆˆˆˆˆˆˆØÑ"""Ò×"""ÒÝ"""ÒÝ"""Ò}b""rÝ"""Òw"ffv݈ˆˆØÝˆˆˆØÝˆˆˆØÝˆˆˆØÝ-""""-""""-""""-""""'f†('-""""''ff&ˆ3ˆˆˆˆˆˆˆˆˆˆˆˆˆˆ-""""-""""-""""-""""'bˆˆ"-""""'‚hf"83ˆˆˆˆˆˆˆˆˆˆˆˆˆˆ-""""-""""-""""-""""'ˆˆˆ(-""""'ˆˆˆ(ˆ3ˆˆˆˆˆˆˆˆˆˆˆˆˆˆ-""""-""""-""""-""""wˆˆˆx-""""wˆˆˆxˆ3ˆˆˆˆˆˆˆˆˆˆˆˆˆˆ-""""-""""-""""-""""'ˆˆˆ(-""""'ˆˆˆ(83‡ˆˆˆˆˆˆˆˆˆˆˆˆˆ-""""-""""-""""-""""'‚ˆˆ"-""""'‚ˆˆ"ˆxwˆˆˆˆˆˆˆˆˆˆˆˆˆÑ"""ÝÝ-""ÝÝ-""ÝÝ-""ÝÝ-ˆ(ÝÝ-""ÝÝ-ˆ(Ý݈‡Ý݈ˆÝ݈ˆÝ݈ˆÝÝ-"Ò""Ò"Ò""Ò"Ò""Ò"Ò""ÒrÒ""Ò"ÒˆˆØrÒ""҈؈ˆØˆØˆˆØˆØˆˆØˆØˆˆØÑÝ-"""Ý-"""Ý-"""Ý-"""}-'""݇ˆˆ}-"""݈ˆˆÝˆˆˆÝˆˆˆÝˆˆˆÑ""""Ò""""Ò""""Ò""""Òrw""ÒxwDˆØ""""Òˆ8ƒˆØˆ8ƒˆØˆˆˆˆØˆˆˆˆØÑ""""Ò""""Ò""""Ò""""Ò"'""Òˆ‡H„Ø""""Òˆ3ƒˆØˆ3ƒˆØˆˆˆˆØˆˆˆˆØÑ""""Ò""""Ò""""Ò""""Ò""Ò"ÒˆHDˆØ""""Òˆ8ƒˆØˆ8ƒˆØˆˆˆˆØˆˆˆˆØÑ""""Ò""""Ò""""Ò""""Ò""Ý-ÒˆDˆˆØ""""Òˆ8ƒˆØˆØƒˆØˆˆˆˆØˆˆˆˆØÑ""""Ò""""Ò""""Ò""""Ò""Ò"ÒˆDD„Ø""""Òˆ33ØØˆÝ=ˆØˆˆˆˆØˆˆˆˆØÑ""""Ò""""Ò""""Ò""""Ò""""ÒˆˆˆˆØ""""ÒˆˆˆÝ݈؈ˆØˆˆˆˆØˆˆˆˆØÑÝÝ""ÒÝÝ""ÒÝÝ""ÒÝÝ""ÒÝÝ""Ý}wˆˆØÝÝ""ÒÝ݈ˆØwwˆˆØÝ݈ˆØÝ݈ˆˆ-""-"-""-"-""-"-""-"-""-ÒÝÝ"‡ˆ-""-"-""ˆ'r"‡ˆˆˆˆˆˆˆØÑ"""ÒÝ"""ÒÝ"""ÒÝ"""ÒÝ"""ÒÝÝÝ"rÝ"""ÒÝ"""Ò}""br݈ˆˆØÝˆˆˆØÝ-""""-""""-""""-""""-""""×Ýf&'-""""-""""''ˆf&ˆ3ˆˆˆˆˆˆ-""""-""""-""""-""""-""""'mff"-""""-'"""'‚ˆh"83ˆˆˆˆˆˆ-""""-""""-""""-""""-""""'hff(-""""}w"""'ˆˆˆ(ˆ3ˆˆˆˆˆˆ-""""-""""-""""-""""-""""whffx-""""-'"""wˆˆˆxˆ3ˆˆˆˆˆˆ-""-"-""""-"""Ý-""""-"ÒÝ"'ˆf†(-""""-""""'ˆˆˆ(83ƒˆˆˆˆˆ-"ÒÝ"-""""-""ÒÝÝ""""-"ÝÝ-'‚ˆˆ"-""""-""""'‚ˆˆ"ˆˆˆˆˆˆˆˆÑ""-ww'""ÝÝ-"ÒÝÝ'""ÝÝ-ÝÝ}w'ˆ(ÝÝ-""ww'""ÝÝ-ˆ(Ý݈ˆÝ݈ˆÝÝ-"r"'r"Ò""Ò"ÒÝÝr"Ò""ÒÝÝ-'rrÒ""Ò"r"'r"Ò""ÒrÒˆˆØˆØˆˆØˆØˆˆØÑÝ'"""×-"""Ý'Ý-"×-"""ÝÝ"""w-"""Ý'"""×-"""}ˆˆˆÝˆˆˆÝˆˆˆqr‚ˆrÒ""""rr‚ˆrÒ""""rr‚ˆrÒ""""rr‚ˆrÒ""""ÒˆDDˆØˆˆˆˆØˆˆˆˆØq"ˆˆ(Ò""""r"ˆˆ(Ò""""r"ˆˆ(Ò""""r"ˆˆ(Ò""""ÒˆˆH„؈ˆˆˆØˆˆˆˆØq‚ˆˆˆÒ""""r‚ˆˆˆÒ""""r‚ˆˆˆÒ""""r‚ˆˆˆÒ""""ÒˆHDˆØˆˆˆˆØˆˆˆˆØq‡ˆˆˆ×""""r‡ˆˆˆ×""""r‡ˆˆˆ×""""r‡ˆˆˆ×""""ÒˆDˆˆØˆˆˆˆØˆˆˆˆØq‚ˆˆˆÒ""""r‚ˆˆˆÒ""""r‚ˆˆˆÒ""""r‚ˆˆˆÒ""""ÒˆDD„؈ˆˆˆØˆˆˆˆØq"ˆˆ(Ò""""r"ˆˆ(Ò""""r"ˆˆ(Ò""""r"ˆˆ(Ò""""ÒˆˆˆˆØˆˆˆˆØˆˆˆˆØÑÝÝ‚ˆÒÝÝ""ÒÝÝ‚ˆÒÝÝ""ÒÝÝ‚ˆÒÝÝ""ÒÝÝ‚ˆÒÝÝ""rwwˆˆØÝ݈ˆØÝ݈ˆˆ-""-'-""-"-""-'-""-"-""-'-""-"-""-'-""-"'r"f†ˆˆˆˆˆˆØÑ"""Ò×"""ÒÝ"""Ò×"""ÒÝ"""Ò×"""ÒÝ"""Ò×"""Ò}""bffˆˆˆØÝˆˆˆØÝ-""""-""""-""""-""""-""""-""""-""""-""""''ˆhffˆ3ˆˆˆˆˆˆ-""""-""""-""""-""""-""""-""""-""""-""""'‚ˆhff83ˆˆˆˆˆˆ-""""-""""-""""-""""-""""-""""-""""-""""'ˆˆˆf†ˆ3ˆˆˆˆˆˆ-""""-""""-""""-""""-""""-""""-""""-""""wˆˆˆxˆ3ˆˆˆˆˆˆ-""""-""""-""""-""""-""""-""""-""""-""""'ˆˆˆ(83ƒˆˆˆˆˆ-""""-""""-""""-""""-""""-""""-""""-""""'‚ˆˆ"ˆˆˆˆˆˆˆˆÑ"""ÝÝ-""ÝÝ-""ÝÝ-""ÝÝ-""ÝÝ-""ÝÝ-""ÝÝ-""ÝÝ-ˆ(Ý݈ˆÝ݈ˆÝÝ-"Ò""Ò"Ò""Ò"Ò""Ò"Ò""Ò"Ò""Ò"Ò""Ò"Ò""Ò"Ò""ÒrÒˆˆØˆØˆˆØˆØˆˆØÑÝ-"""Ý-"""Ý-"""Ý-"""Ý-"""Ý-"""Ý-"""Ý-"""}ˆˆˆÝˆˆˆÝˆˆˆÑ""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""Òˆ8ƒˆØˆˆˆˆØˆˆˆˆØÑ""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""Òˆ3ƒˆØˆˆˆˆØˆˆˆˆØÑ""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""Òˆ8ƒˆØˆˆˆˆØˆˆˆˆØÑ""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""Òˆ8ƒˆØˆˆˆˆØˆˆˆˆØÑ""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""Òˆ33ˆØˆˆˆˆØˆˆˆˆØÑ""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""Ò""""ÒˆˆˆˆØˆˆˆˆØˆˆˆˆØ-"""-"""-"""-"""-"""-"""-"""-"""ˆˆˆˆˆˆˆˆˆÑ""ÒÑ""ÒÑ""ÒÑ""ÒÑ""ÒÑ""ÒÑ""ÒÑ""ÒшˆØшˆØшˆØÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝwwwwwwwwwwwwwwwwwwwwq‡ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ"wˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ(fffffffffffffffffffffffffffffffffffffwˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ(ffffffffffffffffffffffffffffffffffaVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUwˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ(aVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUwˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ(fUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUwˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ(fUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUwˆˆx‡ˆˆˆˆˆˆˆˆˆˆx‡ˆˆˆˆ(fUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUwˆˆxw‡ˆw‡ˆw‡x‡‡x‡ˆˆˆˆ(fUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUUUUUUUuWUUUUUUUUUwUwUuwUUUUUUUUUUUwˆˆx‡xx‡xx‡xxwwx‡ˆˆˆˆ(fUUUUUUUUUUUuwUwUwWuwWUUUUUUUUUUUUUfUUUUUUuWWUUwwUuwUuwWwuwUwUWUUUUUUUUUUwˆˆx‡xx‡xx‡xxxxˆˆˆˆˆˆ(fUUUUUUUUUUUwuWwuWwUUwUUUUUUUUUUUUUfUUUUUUuwwuWwUWwuWwWUUUwUuwUUUUUUUUUUUwˆˆxw‡ˆw‡ˆw‡xxxx‡ˆˆˆˆ(fUUUUUUUUUUUwWWUuwuUwWUUUUUUUUUUUUUfUUUUUUuuuuWwUWwWUUwWwUwUwUWUUUUUUUUUUwˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ(fUUUUUUUUUUUwUWwuWuuWUUUUUUUUUUUUUUfUUUUUUuuuuWwUWuwUwwUwuwWuwUUUUUUUUUUUwˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ(fUUUUUUUUUUUuwUwUwWuwwUUUUUUUUUUUUUfUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUwˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ(fUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUwˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ(fUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUwˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ(fUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUq‡ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ"fUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUaVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU""""""""""""""""""""aVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU€D-- title: mine! hex -- author: aki44 -- local seeded=false local init_done=false cam_x=0 cam_y=0 function set_camera(x,y) cam_x=flr(x or 0) cam_y=flr(y or 0) end function rnd(x) if x == nil then return math.random() end return math.random() * x end function flr(x) return math.floor(x) end function sin(x) return math.sin(x) end function cos(x) return math.cos(x) end function add(t, v) table.insert(t, v) end function del(t, v) for i=1,#t do if t[i] == v then table.remove(t, i) return end end end function all(t) local i=0 return function() i=i+1 return t[i] end end function p8btn(i) local map_ids={ [0]=2,[1]=3,[2]=0,[3]=1,[4]=4,[5]=5 } if i==nil then local mask=0 for k=0,5 do if p8btn(k) then mask=mask+2^k end end return mask end return btn(map_ids[i] or i) end function pset(x,y,c) pix(flr(x),flr(y),c) end function rectfill(x0,y0,x1,y1,c) rect(flr(x0),flr(y0),flr(x1-x0+1),flr(y1-y0+1),c) end function rectb_xyxy(x0,y0,x1,y1,c) rectb(flr(x0),flr(y0),flr(x1-x0+1),flr(y1-y0+1),c) end function circfill(x,y,r,c) circ(flr(x),flr(y),flr(r),c) end function circb2(x,y,r,c) circb(flr(x),flr(y),flr(r),c) end function line2(x0,y0,x1,y1,c) line(flr(x0),flr(y0),flr(x1),flr(y1),c) end function pal() end function palt() end function sfx(_) end -------------------------------------------------- -- game constants -------------------------------------------------- board_w=11 board_h=10 s_block=1 s_empty=2 s_mine=3 s_flag=6 text_colors={3,4,2,9,8,14} hex_dirs_even={ {x=-1,y=0}, {x=1,y=0}, {x=-1,y=-1}, {x=0,y=-1}, {x=-1,y=1}, {x=0,y=1} } hex_dirs_odd={ {x=-1,y=0}, {x=1,y=0}, {x=0,y=-1}, {x=1,y=-1}, {x=0,y=1}, {x=1,y=1} } -------------------------------------------------- -- counters -------------------------------------------------- counters={} function start_ctr(name,v) counters[name]=v end function ctr(name) return counters[name] end function update_ctrs() local to_remove={} for n,v in pairs(counters) do counters[n]=v-1 if counters[n]<0 then add(to_remove,n) end end for n in all(to_remove) do counters[n]=nil end end -------------------------------------------------- -- control modes / pause -------------------------------------------------- control_modes={ "classic", "up=up-right", "up=up-left" } control_mode=1 pause_hold=0 -------------------------------------------------- -- smoke particles -------------------------------------------------- smoke={} smoke_tick=0 function add_smoke(x,y) local life=18+flr(rnd(18)) add(smoke,{ x=x+rnd(5)-2, y=y+rnd(3)-1, dx=rnd(0.8)-0.4, dy=-(rnd(0.5)+0.3), life=life, max_life=life, r=1+flr(rnd(2)) }) end function spawn_bomb_smoke() smoke={} smoke_tick=0 for y=0,board_h-1 do for x=0,board_w-1 do if board[x][y].mine then local sx=hex_screen_x(x,y)+5-cam_x local sy=hex_screen_y(x,y)+6-cam_y for i=1,4 do add_smoke(sx,sy) end end end end end function update_smoke() if status(game)~="lost" then return end smoke_tick=smoke_tick+1 if smoke_tick%3==0 then for y=0,board_h-1 do for x=0,board_w-1 do if board[x][y].mine and rnd(1)<0.35 then add_smoke(hex_screen_x(x,y)+5-cam_x,hex_screen_y(x,y)+6-cam_y) end end end end local dead={} for s in all(smoke) do s.x=s.x+s.dx s.y=s.y+s.dy s.dy=s.dy-0.01 s.dx=s.dx*0.98 s.life=s.life-1 if s.life<=0 then add(dead,s) end end for s in all(dead) do del(smoke,s) end end function draw_smoke() for s in all(smoke) do local age=s.life/s.max_life local c=6 if age<0.66 then c=13 end if age<0.33 then c=7 end circfill(s.x+cam_x,s.y+cam_y,s.r,c) if s.r>1 then pset(s.x+1+cam_x,s.y+cam_y,c) end end end -------------------------------------------------- -- helpers -------------------------------------------------- function clamp(n,low,high) if nhigh then return high end return n end function printc(t,cx,y,clr,scale) scale=scale or 1 local w=#t*6*scale local x=cx-flr(w/2) print(t,x,y,clr,false,scale,false) end function fmt_time(sec) local minutes=flr(sec/60) local secs=sec-minutes*60 if secs<10 then return minutes..":0"..secs else return minutes..":"..secs end end function random_field(b,cond) local x=flr(rnd(board_w)) local y=flr(rnd(board_h)) while not cond(b[x][y]) do x=flr(rnd(board_w)) y=flr(rnd(board_h)) end return {x=x,y=y} end function safe_get(b,x,y) if b[x] and b[x][y] then return b[x][y] else return nil end end function get_dirs_for_row(y) if y%2==0 then return hex_dirs_even else return hex_dirs_odd end end function get_neighbours(b,x,y) local ns={} local dirs=get_dirs_for_row(y) for d in all(dirs) do local n=safe_get(b,x+d.x,y+d.y) if n then add(ns,n) end end return ns end -------------------------------------------------- -- alternate movement helpers -------------------------------------------------- function hex_step_ne(x,y) if y%2==0 then return x,y-1 else return x+1,y-1 end end function hex_step_nw(x,y) if y%2==0 then return x-1,y-1 else return x,y-1 end end function hex_step_se(x,y) if y%2==0 then return x,y+1 else return x+1,y+1 end end function hex_step_sw(x,y) if y%2==0 then return x-1,y+1 else return x,y+1 end end function move_player(p,dx,dy) if control_mode==1 then p.x=clamp(p.x+dx,0,board_w-1) p.y=clamp(p.y+dy,0,board_h-1) return end if dx<0 then p.x=clamp(p.x-1,0,board_w-1) elseif dx>0 then p.x=clamp(p.x+1,0,board_w-1) end if dy<0 then if control_mode==2 then p.x,p.y=hex_step_ne(p.x,p.y) else p.x,p.y=hex_step_nw(p.x,p.y) end elseif dy>0 then if control_mode==2 then p.x,p.y=hex_step_sw(p.x,p.y) else p.x,p.y=hex_step_se(p.x,p.y) end end p.x=clamp(p.x,0,board_w-1) p.y=clamp(p.y,0,board_h-1) end -------------------------------------------------- -- game logic -------------------------------------------------- function start_game(mine_count) board=make_board(mine_count) player={ x=flr(board_w/2), y=flr(board_h/2) } game={ blown_up=false, flags=0, mines_found=0, mines_needed=mine_count, seconds=0 } smoke={} smoke_tick=0 pause_hold=0 make_first_visit(board) state="game" end function status(g) if g.blown_up then return "lost" elseif g.mines_found==g.mines_needed and g.flags==g.mines_needed then return "won" else return "playing" end end function make_board(mine_cnt) local b={} for x=0,board_w-1 do b[x]={} for y=0,board_h-1 do local f={} f.mine=false f.visited=false f.flagged=false b[x][y]=f end end for m=1,mine_cnt do local r=random_field(b, function(field) return not field.mine end ) b[r.x][r.y].mine=true end for x=0,board_w-1 do for y=0,board_h-1 do local neighbours=get_neighbours(b,x,y) local total=0 for n in all(neighbours) do if n.mine then total=total+1 end end b[x][y].mines=total end end return b end function make_first_visit(b) local r=random_field(b, function(f) return f.mines==0 and not f.mine end ) visit(nil,b,r.x,r.y) end function visit(g,b,x,y) local f=safe_get(b,x,y) local skip=(not f) or f.visited or f.flagged if skip then return end if not f.mine then f.visited=true if f.mines==0 then local dirs=get_dirs_for_row(y) for d in all(dirs) do visit(g,b,x+d.x,y+d.y) end return 1 else return 2 end end if g then blow_up(g) end return nil end function flag(g,b,x,y) local f=b[x][y] if f.visited then return end f.flagged=not f.flagged if f.flagged then g.flags=g.flags+1 if f.mine then g.mines_found=g.mines_found+1 end sfx(3) if status(g)=="won" then win(g) end else g.flags=g.flags-1 if f.mine then g.mines_found=g.mines_found-1 end sfx(4) end end function blow_up(g) sfx(0) start_ctr("shake",38) start_ctr("thunder",12) start_ctr("aftershock",24) g.blown_up=true spawn_bomb_smoke() end function win(g) start_ctr("winpulse",90) start_ctr("boardwipe",48) start_ctr("confetti",120) start_ctr("shine",80) end -------------------------------------------------- -- input -------------------------------------------------- delay=0 prev_input=0 function parse_input() local dx=0 local dy=0 if delay==0 then if p8btn(0) then dx=dx-1 end if p8btn(1) then dx=dx+1 end if p8btn(2) then dy=dy-1 end if p8btn(3) then dy=dy+1 end end local action=nil if prev_input<16 then if p8btn(4) then action="first" end if p8btn(5) then action="second" end end if p8btn(4) and p8btn(5) then pause_hold=pause_hold+1 else pause_hold=0 end local pause_pressed=(pause_hold==12) if p8btn()~=0 and delay==0 then if prev_input~=0 then delay=2 else delay=7 end end if p8btn()==0 then delay=0 end delay=clamp(delay-1,0,8) prev_input=p8btn() return { dx=dx, dy=dy, action=action, pause=pause_pressed } end -------------------------------------------------- -- game main loop -------------------------------------------------- function update_game() local st=status(game) local inp=parse_input() if inp.pause then state="pause" return end if st~="playing" then if inp.action then state="menu" end update_smoke() return end local p=player move_player(p,inp.dx,inp.dy) if inp.action=="first" then local snd=visit(game,board,p.x,p.y) if snd then sfx(snd) end end if inp.action=="second" then flag(game,board,p.x,p.y) end if t%60==0 then game.seconds=game.seconds+1 end update_smoke() end function update_pause() local inp=parse_input() if inp.pause or inp.action then state="game" pause_hold=0 return end if inp.dx~=0 then control_mode=clamp(control_mode+inp.dx,1,#control_modes) sfx(2) end end -------------------------------------------------- -- drawing helpers -------------------------------------------------- function draw_bevel_panel(x0,y0,x1,y1,fillc,lightc,darkc) rectfill(x0+2,y0,x1-2,y1,fillc) rectfill(x0,y0+2,x1,y1-2,fillc) line2(x0+2,y0,x1-2,y0,lightc) line2(x0+1,y0+1,x0+1,y1-1,lightc) line2(x0,y0+2,x0,y1-2,lightc) line2(x1-2,y1,x0+2,y1,darkc) line2(x1-1,y1-1,x1-1,y0+1,darkc) line2(x1,y1-2,x1,y0+2,darkc) pset(x0+1,y0+1,lightc) pset(x0+2,y0+1,lightc) pset(x0+1,y0+2,lightc) pset(x1-1,y0+1,darkc) pset(x1-2,y0+1,darkc) pset(x1-1,y0+2,darkc) pset(x0+1,y1-1,lightc) pset(x0+2,y1-1,lightc) pset(x1-1,y1-1,darkc) pset(x1-2,y1-1,darkc) end -------------------------------------------------- -- menu -------------------------------------------------- difficulties={ {n="easy peasy",m=10}, {n="just ok",m=18}, {n="harder",m=26}, {n="super hard",m=34} } diff=2 floaters={} for i=1,18 do add(floaters,{ x=rnd(240), y=rnd(136), dx=rnd(1.4)-0.7, dy=rnd(1.4)-0.7 }) end function update_floaters() for f in all(floaters) do f.x=f.x+f.dx f.y=f.y+f.dy if f.x<-16 then f.x=240+rnd(8) end if f.x>240 then f.x=-16-rnd(8) end if f.y<-16 then f.y=136+rnd(8) end if f.y>136 then f.y=-16-rnd(8) end if rnd(1)<0.03 then f.dx=clamp(f.dx+rnd(0.5)-0.25,-0.9,0.9) f.dy=clamp(f.dy+rnd(0.5)-0.25,-0.9,0.9) end end end function draw_tiny_hex(x,y,c1,c2) draw_hex_tile(x,y,c1,c2) end function draw_menu_logo() draw_bevel_panel(56,10,184,42,5,6,1) printc("hex mine",120,20,12,2) printc("hexagonal minesweeper",122,33,13,1) end function draw_menu() cls(1) for f in all(floaters) do draw_tiny_hex(f.x,f.y,5,13) end draw_menu_logo() local d=difficulties[diff] printc("skill level",120,60,13,1) printc(d.n,120,74,15,2) local blink=(t%30<15) if diff>1 and blink then printc("<",58,74,10,2) end if diff<4 and blink then printc(">",182,74,10,2) end printc("z reveals a hex",120,102,6,1) printc("x plants a flag",120,112,7,1) printc("left/right picks difficulty",120,122,5,1) printc("press z or x to start",120,130,12,1) end function update_menu() update_floaters() local inp=parse_input() if inp.action then local d=difficulties[diff] start_game(d.m) end if inp.dx~=0 then diff=clamp(diff+inp.dx,1,4) sfx(2) end end -------------------------------------------------- -- hex board drawing -------------------------------------------------- hex_w=11 hex_h=12 hex_xstep=10 hex_ystep=9 function hex_screen_x(x,y) return cam_x+60+x*hex_xstep+((y%2)*5) end function hex_screen_y(x,y) return cam_y+8+y*hex_ystep end function draw_hex_fill(x,y,c) rectfill(x+3,y,x+7,y+11,c) rectfill(x+2,y+1,x+8,y+10,c) rectfill(x+1,y+2,x+9,y+9,c) rectfill(x,y+3,x+10,y+8,c) end function draw_hex_outline(x,y,c) line2(x+3,y,x+7,y,c) line2(x+7,y,x+10,y+3,c) line2(x+10,y+3,x+10,y+8,c) line2(x+10,y+8,x+7,y+11,c) line2(x+7,y+11,x+3,y+11,c) line2(x+3,y+11,x,y+8,c) line2(x,y+8,x,y+3,c) line2(x,y+3,x+3,y,c) end function draw_hex_tile(x,y,fillc,outlinec) draw_hex_fill(x,y,fillc) draw_hex_outline(x,y,outlinec) end function draw_hex_mine(x,y) circfill(x+5,y+6,3,8) pset(x+5,y+1,7) pset(x+5,y+10,7) pset(x+1,y+6,7) pset(x+9,y+6,7) pset(x+2,y+3,7) pset(x+8,y+3,7) pset(x+2,y+9,7) pset(x+8,y+9,7) end function draw_hex_flag(x,y) line2(x+5,y+2,x+5,y+9,0) line2(x+5,y+2,x+8,y+4,8) line2(x+8,y+4,x+5,y+5,8) line2(x+3,y+9,x+6,y+9,0) end function draw_board(g,b) local st=status(g) local bw=999 if st=="won" then bw=ctr("boardwipe") or 0 end for y=0,board_h-1 do for x=0,board_w-1 do local f=b[x][y] local sx=hex_screen_x(x,y) local sy=hex_screen_y(x,y) local fillc=2 local linec=13 if st=="lost" and f.mine then fillc=2 linec=7 elseif f.visited then fillc=8 elseif f.flagged then fillc=1 end if ctr("shine") and st=="won" and flr((x+y+t)/8)%2==0 then fillc=10 end if x+y0 then local clr=text_colors[f.mines] or 15 print(tostring(f.mines),sx+3,sy+3,clr,false,1,false) end end end end end function draw_player(g,p) if status(g)~="playing" then return end local x=hex_screen_x(p.x,p.y) local y=hex_screen_y(p.x,p.y) local c1=(t%16<8) and 10 or 8 local c2=(t%16<8) and 7 or 12 draw_hex_outline(x,y,c1) draw_hex_outline(x+1,y+1,c2) end function draw_hud(g) local st=status(g) local mines_left=g.mines_needed-g.flags local tstr=fmt_time(g.seconds) draw_bevel_panel(6,117,84,133,5,6,1) printc("mines:"..mines_left,45,123,7,1) draw_bevel_panel(160,117,232,133,5,6,1) printc(tstr,196,123,7,1) if st=="lost" then draw_bevel_panel(98,114,142,132,8,7,2) printc("boom!",120,121,7,1) end end function draw_win() local minutes=flr(game.seconds/60) local secs=game.seconds-minutes*60 local secstr=(secs<10) and ("0"..secs) or tostring(secs) local tstr=minutes..":"..secstr local pulse=ctr("winpulse") or 0 local clr=(pulse%10<5) and 10 or 7 draw_bevel_panel(70,18,170,56,11,10,3) printc("you win!",120,25,7,1) printc("clear time",120,37,6,1) printc(tstr,120,47,clr,2) end function draw_thunder() local th=ctr("thunder") if not th then return end local phase=12-th local cx=hex_screen_x(player.x,player.y)+5 local cy=hex_screen_y(player.x,player.y)+6 if phase<=2 then rectfill(0,0,239,135,7) elseif phase<=4 then rectfill(0,0,239,135,10) elseif phase<=6 then rectfill(0,0,239,135,9) end local r1=phase*10 local r2=phase*6 circfill(cx,cy,r1,7) circfill(cx,cy,r2,10) for i=0,7 do local a=(i/8)*(math.pi*2) local dx=cos(a)*r1 local dy=sin(a)*r1 line2(cx,cy,cx+dx,cy+dy,8) line2(cx+dx*0.5,cy+dy*0.5,cx+dx*1.2,cy+dy*1.2,10) end circb2(cx,cy,r1+3,8) circb2(cx,cy,r2+2,7) end function draw_confetti() local c=ctr("confetti") if not c then return end for i=1,18 do local px=(i*19+t*2)%240 local py=(i*11+t*3+i*i)%90 pset(px+cam_x,py+cam_y,(flr((i+t)/3)%15)+1) pset((239-px)+cam_x,py+8+cam_y,(flr((i*2+t)/4)%15)+1) end end function draw_pause() draw_game() rectfill(45,18,195,94,1) rectb_xyxy(45,18,195,94,7) printc("paused",120,28,7,2) printc("control style",120,46,6,1) printc(control_modes[control_mode],120,58,10,1) printc("left/right changes scheme",120,72,5,1) printc("hold z+x to resume",120,82,5,1) printc("classic: square cursor move",120,90,5,1) end function draw_game() cls(1) local shake=ctr("shake") local after=ctr("aftershock") if shake then local mag=shake*0.55 local dx=sin(t*0.09)*mag local dy=cos(t*0.12)*mag set_camera(dx,dy) elseif after then local mag=after*0.08 set_camera(sin(t*0.17)*mag,cos(t*0.11)*mag) else set_camera(0,0) end if status(game)=="won" then draw_board(game,board) draw_confetti() draw_win() draw_hud(game) else draw_board(game,board) draw_player(game,player) draw_hud(game) end if status(game)=="lost" then draw_smoke() draw_hud(game) end draw_thunder() end -------------------------------------------------- -- main -------------------------------------------------- t=0 state="menu" function _init() state="menu" end function _update() t=t+1 update_ctrs() if state=="game" then update_game() elseif state=="pause" then update_pause() else update_menu() end end function _draw() set_camera(0,0) pal() palt(0,false) palt(14,true) if state=="game" then draw_game() elseif state=="pause" then draw_pause() else draw_menu() end end function TIC() if not seeded then math.randomseed(time()) seeded=true end if not init_done then _init() init_done=true end _update() _draw() end