import curses import random import copy from var_config import * def begin_curses(): stdscr = curses.initscr() curses.noecho() curses.cbreak() curses.curs_set(0) stdscr.keypad(True) #stdscr.nodelay(True) curses.start_color() curses.init_pair(SIMPLE_COLOR, curses.COLOR_WHITE, curses.COLOR_BLACK) curses.init_pair(ACTIVE_COLOR, curses.COLOR_BLACK, curses.COLOR_WHITE) curses.init_pair(WALL_COLOR, curses.COLOR_WHITE, curses.COLOR_BLACK) curses.init_pair(GOLD_COLOR, curses.COLOR_YELLOW, curses.COLOR_BLACK) curses.init_pair(WEAPON_COLOR, curses.COLOR_CYAN, curses.COLOR_BLACK) curses.init_pair(HIGHLIGHTED_COLOR, curses.COLOR_CYAN, curses.COLOR_BLACK) curses.init_pair(PLAYER_COLOR, curses.COLOR_BLACK, curses.COLOR_WHITE) curses.init_pair(DOOR_COLOR, curses.COLOR_BLUE, curses.COLOR_BLACK) curses.init_pair(MONSTER_COLOR, curses.COLOR_RED, curses.COLOR_BLACK) curses.init_pair(ADD_HEALTH_COLOR, curses.COLOR_GREEN, curses.COLOR_BLACK) curses.init_pair(SCORE_COLOR, curses.COLOR_GREEN, curses.COLOR_BLACK) curses.init_pair(ACTIVE_WEAPON_COLOR, curses.COLOR_YELLOW, curses.COLOR_BLACK) return stdscr def end_curses(stdscr): #stdscr.nodelay(False) stdscr.keypad(False) curses.curs_set(1) curses.nocbreak() curses.echo() curses.endwin() def gen_map_step(map): tmp_map = copy.deepcopy(map) for i in range(1, len(map) - 1): for j in range(1, len(map[i]) - 1): x = 0 for d in EXTENDED_DIRECTIONS: if tmp_map[i + d[0]][j + d[1]][0] == WALL: x += 1 if x < 2 or x >= 4: map[i][j] = [EMPTY, SIMPLE_COLOR] elif x >= 3 and x <= 3: map[i][j] = [WALL, WALL_COLOR] def generate_map(map, sz_x, sz_y, map_symbols, automata_iterations, wall_rand_range, wall_rand_gen): rand_sum = 0 for symbol in map_symbols: rand_sum += symbol[1] for i in range(sz_x): map.append([]) for j in range(sz_y): if i == 0 or j == 0 or i == sz_x - 1 or j == sz_y - 1: map[i].append([WALL, WALL_COLOR]) else: if random.randint(1, wall_rand_range) <= wall_rand_gen: map[i].append([WALL, WALL_COLOR]) else: map[i].append([EMPTY, SIMPLE_COLOR]) for i in range(automata_iterations): gen_map_step(map) for i in range(1, len(map) - 1): for j in range(1, len(map[i]) - 1): if (map[i][j][0] == EMPTY): x = random.randint(1, rand_sum) for symbol in map_symbols: x -= symbol[1] if x <= 0: map[i][j] = symbol[0] break def map_mark_dfs(map, i, j): if map[i][j][0] == WALL or map[i][j][0] == MARK: return [] positions = [(i, j)] map[i][j] = (MARK, SIMPLE_COLOR) for d in DIRECTIONS: # walls on all sides, then no check needed there new_positions = map_mark_dfs(map, i + d[0], j + d[1]) for pos in new_positions: positions.append(pos) return positions def generate_doors(map): doors = [] tmp_map = copy.deepcopy(map) for i in range(len(tmp_map)): for j in range(len(tmp_map[i])): if tmp_map[i][j][0] == EMPTY: map_mark_dfs(tmp_map, i, j) map[i][j] = [DOOR, DOOR_COLOR] doors.append([i, j]) return doors def random_direction(): k = random.randint(0, 3) return [((k % 2) * 2 - 1) * (k // 2), ((k % 2) * 2 - 1) * (1 - k // 2)] def generate_monsters(map, rand_range, rand_monster): monsters = [] for i in range(len(map)): for j in range(len(map[i])): if map[i][j][0] == EMPTY and \ random.randint(1, rand_range) <= rand_monster: monsters.append([[i, j], random_direction()]) return monsters def move_monsters(map, monsters): for i in range(len(monsters)): pos = [0, 0] pos[0] = monsters[i][0][0] + monsters[i][1][0] pos[1] = monsters[i][0][1] + monsters[i][1][1] if map[pos[0]][pos[1]][0] != WALL: monsters[i][0] = pos pass else: monsters[i][1] = random_direction() pass def damage_player(monsters, player_state): for m in monsters: if abs(player_state[P_POS][0] - m[0][0]) + abs(player_state[P_POS][1] - m[0][1]) <= 1: player_state[P_HEALTH] -= MONSTER_DAMAGE pass def game_step(map, monsters, player_state, doors): #if player_pos == door for any door ? move_monsters(map, monsters) damage_player(monsters, player_state) pass def draw(stdscr, map, monsters, active_weapon, player_state): stdscr.addstr(0, 0, str(player_state)) info_str = [ "Health: " + str(player_state[P_HEALTH]), "Weapon: " + str(player_state[P_WEAPON]), "Gold: " + str(player_state[P_GOLD]), "Score: " + str(player_state[P_SCORE]), "", "Help:", "", "ARROWS - move", "", "WASD - use", "weapon", "", "QE - move", "through doors", "", "You must", "collect", "all score", "", "% - weapon", "# - wall", "@ - score", "M - monster", "P - player", "> - door", "$ - money", "+ - add health" ] for i in range(len(info_str)): stdscr.addstr(MAP_POS_Y - 1 + i, 0, info_str[i], curses.color_pair(HIGHLIGHTED_COLOR)) for i in range(len(map)): stdscr.addstr(MAP_POS_Y - 1, i + MAP_POS_X, '-', curses.color_pair(SIMPLE_COLOR)) stdscr.addstr(len(map[0]) + MAP_POS_Y, i + MAP_POS_X, '-', curses.color_pair(SIMPLE_COLOR)) for i in range(len(map[0])): # ?? better ?? stdscr.addstr(i + MAP_POS_Y, MAP_POS_X - 1, '|', curses.color_pair(SIMPLE_COLOR)) stdscr.addstr(i + MAP_POS_Y, len(map) + MAP_POS_X, '|', curses.color_pair(SIMPLE_COLOR)) for i in range(len(map)): for j in range(len(map[i])): stdscr.addstr(j + MAP_POS_Y, i + MAP_POS_X, map[i][j][0], curses.color_pair(map[i][j][1])) for m in monsters: stdscr.addstr(m[0][1] + MAP_POS_Y, m[0][0] + MAP_POS_X, MONSTER, curses.color_pair(MONSTER_COLOR)) for w in active_weapon: stdscr.addstr(w[0][1] + MAP_POS_Y, w[0][0] + MAP_POS_X, ACTIVE_WEAPON, curses.color_pair(ACTIVE_WEAPON_COLOR)) stdscr.addstr(MAP_POS_Y + player_state[P_POS][1], MAP_POS_X + player_state[P_POS][0], PLAYER, curses.color_pair(PLAYER_COLOR)) def input(stdscr): # not work m = [0, 0] key = "" try: key = stdscr.getkey() if key == MOVE_UP_ACTION: m[1] -= 1 elif key == MOVE_DOWN_ACTION: m[1] += 1 elif key == MOVE_LEFT_ACTION: m[0] -= 1 elif key == MOVE_RIGHT_ACTION: m[0] += 1 except: pass # no input return (m, key) pass def move_player(map, player_state, pos_change): p = copy.deepcopy(player_state[0]) p[0] += pos_change[0] p[1] += pos_change[1] x = map[p[0]][p[1]][0] if x != WALL: player_state[0] = p if x == ADD_HEALTH: player_state[P_HEALTH] += 1 elif x == WEAPON: player_state[P_WEAPON] += 1 elif x == GOLD: player_state[P_GOLD] += 1 elif x == SCORE: player_state[P_SCORE] += 1 if x != WALL and x != DOOR: map[p[0]][p[1]] = [EMPTY, SIMPLE_COLOR] def use_weapon(map, active_weapon, player_state, direction): if player_state[P_WEAPON] <= 0: return p = copy.deepcopy(player_state[P_POS]) p[0] += direction[0] p[1] += direction[1] if map[p[0]][p[1]][0] == WALL: if p[0] != 0 and p[1] != 0 and p[0] != len(map) - 1 and p[1] != len(map[0]): map[p[0]][p[1]] = [EMPTY, SIMPLE_COLOR] player_state[P_WEAPON] -= 1 else: active_weapon.append([p, copy.deepcopy(direction)]) player_state[P_WEAPON] -= 1 def player_actions(map, doors, active_weapon, player_state, player_action): k = -1 if player_action == ATTACK_UP_ACTION: k = 0 elif player_action == ATTACK_DOWN_ACTION: k = 1 elif player_action == ATTACK_LEFT_ACTION: k = 2 elif player_action == ATTACK_RIGHT_ACTION: k = 3 if k >= 0: use_weapon(map, active_weapon, player_state, DIRECTIONS[k]) if not doors[player_state[P_ACTIVE_DOOR]]: return if player_action == NEXT_DOOR_ACTION: player_state[P_ACTIVE_DOOR] += 1 player_state[P_ACTIVE_DOOR] %= len(doors) player_state[P_POS] = copy.deepcopy( doors[player_state[P_ACTIVE_DOOR]]) elif player_action == PREV_DOOR_ACTION: player_state[P_ACTIVE_DOOR] = (player_state[P_ACTIVE_DOOR] + len(doors) - 1) % len(doors) player_state[P_POS] = copy.deepcopy( doors[player_state[P_ACTIVE_DOOR]]) def move_weapon(map, active_weapon, player_state): # needed to test remove_list = [] for i in range(len(active_weapon)): p = copy.deepcopy(active_weapon[i][0]) p[0] += active_weapon[i][1][0] p[1] += active_weapon[i][1][1] if map[p[0]][p[1]][0] == WALL or \ map[p[0]][p[1]][0] == DOOR: p = active_weapon[i][0] if map[p[0]][p[1]][0] == SCORE: player_state[P_SCORE] += 1 map[p[0]][p[1]] = [WALL, WALL_COLOR] remove_list.append(i) else: active_weapon[i][0] = p for i in remove_list: active_weapon.remove(active_weapon[i]) def calc_max_score(map): max_score = 0 for row in map: for cell in row: if cell[0] == SCORE: max_score += 1 return max_score def main(): map_symbols = [ [[EMPTY, SIMPLE_COLOR], 90], [[GOLD, GOLD_COLOR], 2], [[WEAPON, WEAPON_COLOR], 4], [[ADD_HEALTH, ADD_HEALTH_COLOR], 2], [[SCORE, SCORE_COLOR], 2] ] stdscr = begin_curses() map_size = [40, 20] active_weapon = [] # positions of active weapon map = [] generate_map(map, map_size[0], map_size[1], map_symbols, 20, 100, 45) doors = generate_doors(map) monsters = generate_monsters(map, 100, 3) max_score = calc_max_score(map) player_state = [doors[0], 10, 2, 0, 0, 0] # pos = [x, y], lives, weapon, money, active door, score main_loop_exception = False player_win = False try: while(True): stdscr.clear() game_step(map, monsters, player_state, doors) draw(stdscr, map, monsters, active_weapon, player_state) stdscr.refresh() pos_change, player_action = input(stdscr) move_player(map, player_state, pos_change) player_actions(map, doors, active_weapon, player_state, player_action) for i in range(WEAPON_SPEED): move_weapon(map, active_weapon, player_state) if player_state[P_HEALTH] <= 0: break if player_state[P_SCORE] == max_score: player_win = True break # win except: main_loop_exception = True end_curses(stdscr) if main_loop_exception: print("Error during main loop") elif player_win: print("You win!") else: print("You lose(") if (__name__ == "__main__"): main()