diff options
Diffstat (limited to 'sweepy.py')
| -rwxr-xr-x | sweepy.py | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/sweepy.py b/sweepy.py new file mode 100755 index 0000000..bc173f5 --- /dev/null +++ b/sweepy.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python3 + +import curses +from logic import MinesweeperLogic +from ouija import Ouija, Tile +from pathlib import Path +import os + +HOME = Path(os.environ["HOME"]) +SWEEPY_ROOT = ".sweepy" +MY_SWEEPY_ROOT = HOME / SWEEPY_ROOT +MY_SWEEPY_WON = MY_SWEEPY_ROOT / "won" +MY_SWEEPY_LOST = MY_SWEEPY_ROOT / "lost" + +def generate_tiles(): + + tiles = [] + tiles.append(Tile("0", "")) + tiles.append(Tile("1", "1", Ouija.COLORS["DEFAULT"], curses.A_BOLD)) + tiles.append(Tile("2", "2", Ouija.COLORS["BLUE"], curses.A_BOLD)) + tiles.append(Tile("3", "3", Ouija.COLORS["RED"], curses.A_BOLD)) + tiles.append(Tile("4", "4", Ouija.COLORS["GREEN"], curses.A_BOLD)) + tiles.append(Tile("5", "5", Ouija.COLORS["ORANGE"], curses.A_BOLD)) + tiles.append(Tile("!", "#", Ouija.COLORS["YELLOW"])) + tiles.append(Tile("_", ".")) + tiles.append(Tile("x", "x", Ouija.COLORS["BLACK_ON_YELLOW"])) + tiles.append(Tile("-", ".", Ouija.COLORS["BLACK_ON_YELLOW"])) + tiles.append(Tile("+", "#", Ouija.COLORS["BLACK_ON_YELLOW"])) + return tiles + +def env_setup(): + if not MY_SWEEPY_ROOT.exists(): + MY_SWEEPY_ROOT.mkdir() + if not MY_SWEEPY_WON.exists(): + MY_SWEEPY_WON.mkdir() + if not MY_SWEEPY_LOST.exists(): + MY_SWEEPY_LOST.mkdir() + +def game_loop(stdscr, ob, ml): + + cur_y, cur_x = ml.get_first_cell() + + while(True): + + if ml.has_won() or ml.has_lost(): + msg = "You won!" if ml.has_won() else "You lost :(" + base_fn = MY_SWEEPY_WON if ml.has_won() else MY_SWEEPY_LOST + + stdscr.addstr(4, 3, "{} [n]ew game, [r]eplay, or [q]uit?".format(msg)) + ob.draw_board(ml.get_board()) + + fn = "{}.sweepy".format(ml.SEED) + root_fn = MY_SWEEPY_ROOT / fn + fn_fq = MY_SWEEPY_WON / fn + if root_fn.exists(): + root_fn.unlink() + + ml.save(str(fn_fq)) + + while(True): + + ik = stdscr.getkey() + if ik == 'n': + # clear the line + stdscr.move(4, 3) + stdscr.clrtoeol() + + ml = MinesweeperLogic() + ml.new_game() + cur_y, cur_x = ml.get_first_cell() + break + + elif ik == 'r': + stdscr.move(4, 3) + stdscr.clrtoeol() + ml.new_game() + cur_y, cur_x = ml.get_first_cell() + break + + elif ik == 'q': + exit() + + game_head(stdscr, ml) + game_foot(stdscr) + ob.draw_board(ml.get_board(), cur_y, cur_x) + in_key = stdscr.getkey() + + # uncover a cell using the enter key + if in_key == "\n": + ml.do_move(cur_y, cur_x, "u") + if ml.get_first_cell(): + cur_y, cur_x = ml.get_closest_cell(cur_y, cur_x) + #cur_y, cur_x = ml.closest(cur_y, cur_x) + + # flag a cell using the "f" key + elif in_key == "f": + ml.do_move(cur_y, cur_x, "x") + if ml.get_first_cell(): + cur_y, cur_x = ml.get_closest_cell(cur_y, cur_x) + #cur_y, cur_x = ml.closest(cur_y, cur_x) + + # save a game (and exit) using the "s" key + elif in_key == "s": + ob.draw_board(ml.get_board()) + fn = "{}.sweepy".format(ml.SEED) + root_fn = MY_SWEEPY_ROOT / fn + ml.save(str(root_fn)) + stdscr.addstr(4, 3, "Game saved!") + stdscr.getch() + exit() + + # start a new game with the "n" key + elif in_key == "n": + ob.draw_board(ml.get_board()) + stdscr.addstr(4, 3, "new game? (y/n) ") + choice = stdscr.getkey() + stdscr.move(4, 3) + stdscr.clrtoeol() + + if choice == 'y': + ml = MinesweeperLogic() + ml.new_game() + cur_y, cur_x = ml.get_first_cell() + + # reset the current game with the "r" key + elif in_key == "r": + ob.draw_board(ml.get_board()) + stdscr.addstr(4, 3, "reset the current game? (y/n) ") + choice = stdscr.getkey() + stdscr.move(4, 3) + stdscr.clrtoeol() + + if choice == 'y': + ml.new_game() + cur_y, cur_x = ml.get_first_cell() + + # quit without saving using the "q" key + elif in_key == "q": + ob.draw_board(ml.get_board()) + stdscr.addstr(4, 3, "Quit without saving? (y/n) ") + choice = stdscr.getkey() + if choice == 'y': + exit() + else: + stdscr.move(4, 3) + stdscr.clrtoeol() + + # navigation + elif in_key == "KEY_LEFT": + cur_y, cur_x, cost = ml.get_left(cur_y, cur_x) + elif in_key == "KEY_RIGHT": + cur_y, cur_x, cost = ml.get_right(cur_y, cur_x) + elif in_key == "KEY_UP": + cur_y, cur_x, cost = ml.get_up(cur_y, cur_x) + elif in_key == "KEY_DOWN": + cur_y, cur_x, cost = ml.get_down(cur_y, cur_x) + elif in_key == "\t": + cur_y, cur_x = ml.closest(cur_y, cur_x) + +def game_head(stdscr, ml): + stdscr.addstr(1, 3, "~ sweepy ~") + stdscr.addstr(2, 3, "{} bombs, seed: {}".format(str(ml.BOMBS),str(ml.SEED))) + stdscr.addstr(3, 3, "flags: {:>2}".format(str(ml.get_flag_count()))) + stdscr.refresh() + +def game_foot(stdscr): + stdscr.addstr(24, 3, "u/d/l/r/tab navigation") + stdscr.addstr(25, 3, "enter: uncover cell") + stdscr.addstr(26, 3, "'f': (un)flag cell") + stdscr.addstr(27, 3, "'n': new game") + stdscr.addstr(28, 3, "'r': reset game") + stdscr.addstr(29, 3, "'s': save and quit game") + stdscr.addstr(30, 3, "'q': quit game (without saving)") + +def main(stdscr): + + stdscr.clear() + curses.curs_set(False) + + env_setup() + + # blocks are 2 tall and 4 wide + ml = MinesweeperLogic() + board = Ouija(stdscr, 6, 5) + board.style(corner=None, horiz_edge="=") + + if not board.setup_tiles(generate_tiles()): + return False + + # print some info + stdscr.addstr(1, 3, "~ sweepy ~") + stdscr.addstr(2, 3, "[n]ew game, or [r]esume a game") + + # initial loop + while(True): + in_key = stdscr.getkey() + + if in_key == "q": + exit() + elif in_key == "n": + stdscr.addstr(3, 3, "choose a size") + stdscr.addstr(4, 3, "[0] 8 x 8 (10 bombs)") + stdscr.addstr(5, 3, "[1] 16 x 8 (25 bombs)") + while True: + choice = stdscr.getkey() + if choice == '0': + ml.new_game(8, 8, 10) + break + elif choice == '1': + ml.new_game(8, 16, 25) + break + else: + stdscr.addstr(6, 3, "invalid choice, choose again") + break + elif in_key == "l": + stdscr.addstr(3, 3, "what game do you want to load? ") + fn = stdscr.getstr() + stdscr.addstr(4, 3, fn) + stdscr.getch() + ml.load(fn.decode('utf-8')) + break + elif in_key == "r": + current_games = sorted(MY_SWEEPY_ROOT.glob("*.sweepy")) + stdscr.addstr(3, 3, "there are " + str(len(current_games)) + " games in progress") + for idx, game in enumerate(current_games): + stdscr.addstr(4 + idx, 3, "[{}] {}".format(str(idx), str(game.name))) + + if len(current_games) != 0: + stdscr.addstr(4 + len(current_games), 3, "choose a game") + while True: + r_key = stdscr.getkey() + if r_key.isdigit() and int(r_key) in range(len(current_games)): + r_game = current_games[int(r_key)] + ml.load(str(r_game)) + break + else: + stdscr.addstr(4 + len(current_games), 3, "invalid choice, choose a game") + break + + stdscr.clear() + game_loop(stdscr, board, ml) + +curses.wrapper(main) |
