python_curses_game_2021/proj/main.py

412 lines
9.8 KiB
Python
Raw Normal View History

2021-04-12 21:17:06 +03:00
import curses
2021-04-12 22:11:38 +03:00
import random
2021-04-13 01:20:31 +03:00
import copy
2021-04-12 21:17:06 +03:00
2021-05-29 19:39:39 +03:00
from var_config import *
2021-04-12 21:17:06 +03:00
2021-04-12 22:11:38 +03:00
def begin_curses():
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
curses.curs_set(0)
stdscr.keypad(True)
2021-04-14 23:50:31 +03:00
#stdscr.nodelay(True)
2021-04-12 21:17:06 +03:00
2021-04-12 22:11:38 +03:00
curses.start_color()
2021-04-12 21:17:06 +03:00
2021-04-12 22:11:38 +03:00
curses.init_pair(SIMPLE_COLOR, curses.COLOR_WHITE, curses.COLOR_BLACK)
curses.init_pair(ACTIVE_COLOR, curses.COLOR_BLACK, curses.COLOR_WHITE)
2021-04-13 01:20:31 +03:00
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)
2021-04-14 23:50:31 +03:00
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)
2021-04-15 14:25:58 +03:00
curses.init_pair(SCORE_COLOR, curses.COLOR_GREEN, curses.COLOR_BLACK)
curses.init_pair(ACTIVE_WEAPON_COLOR, curses.COLOR_YELLOW, curses.COLOR_BLACK)
2021-04-12 21:17:06 +03:00
2021-04-12 22:11:38 +03:00
return stdscr
2021-04-12 21:17:06 +03:00
2021-04-12 22:11:38 +03:00
def end_curses(stdscr):
2021-04-14 23:50:31 +03:00
#stdscr.nodelay(False)
2021-04-12 22:11:38 +03:00
stdscr.keypad(False)
2021-04-13 01:20:31 +03:00
curses.curs_set(1)
curses.nocbreak()
2021-04-12 22:11:38 +03:00
curses.echo()
curses.endwin()
2021-04-14 23:50:31 +03:00
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:
2021-04-15 14:25:58 +03:00
if tmp_map[i + d[0]][j + d[1]][0] == WALL:
x += 1
if x < 2 or x >= 4:
2021-04-15 14:25:58 +03:00
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):
2021-04-12 22:18:20 +03:00
rand_sum = 0
2021-04-13 01:20:31 +03:00
for symbol in map_symbols:
rand_sum += symbol[1]
2021-04-12 22:18:20 +03:00
2021-04-14 23:50:31 +03:00
for i in range(sz_x):
2021-04-13 01:20:31 +03:00
map.append([])
2021-04-14 23:50:31 +03:00
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):
2021-04-14 23:50:31 +03:00
x = random.randint(1, rand_sum)
for symbol in map_symbols:
x -= symbol[1]
if x <= 0:
map[i][j] = symbol[0]
2021-04-14 23:50:31 +03:00
break
2021-04-12 22:11:38 +03:00
2021-04-13 01:20:31 +03:00
def map_mark_dfs(map, i, j):
2021-04-15 00:24:44 +03:00
if map[i][j][0] == WALL or map[i][j][0] == MARK:
2021-04-14 23:50:31 +03:00
return []
2021-04-13 01:20:31 +03:00
positions = [(i, j)]
2021-04-14 23:50:31 +03:00
2021-04-13 01:20:31 +03:00
map[i][j] = (MARK, SIMPLE_COLOR)
for d in DIRECTIONS:
2021-04-14 23:50:31 +03:00
# 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)
2021-04-13 01:20:31 +03:00
return positions
def generate_doors(map):
doors = []
tmp_map = copy.deepcopy(map)
2021-04-14 23:50:31 +03:00
2021-04-13 01:20:31 +03:00
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)
2021-04-14 23:50:31 +03:00
map[i][j] = [DOOR, DOOR_COLOR]
doors.append([i, j])
return doors
2021-04-13 01:20:31 +03:00
def random_direction():
k = random.randint(0, 3)
2021-04-14 23:50:31 +03:00
return [((k % 2) * 2 - 1) * (k // 2),
((k % 2) * 2 - 1) * (1 - k // 2)]
2021-04-13 01:20:31 +03:00
def generate_monsters(map, rand_range, rand_monster):
monsters = []
for i in range(len(map)):
for j in range(len(map[i])):
2021-05-29 19:39:39 +03:00
if map[i][j][0] == EMPTY and \
random.randint(1, rand_range) <= rand_monster:
monsters.append([[i, j], random_direction()])
2021-04-13 01:20:31 +03:00
return monsters
def move_monsters(map, monsters):
for i in range(len(monsters)):
2021-04-14 23:50:31 +03:00
pos = [0, 0]
pos[0] = monsters[i][0][0] + monsters[i][1][0]
pos[1] = monsters[i][0][1] + monsters[i][1][1]
2021-04-15 14:25:58 +03:00
if map[pos[0]][pos[1]][0] != WALL:
2021-04-14 23:50:31 +03:00
monsters[i][0] = pos
pass
else:
monsters[i][1] = random_direction()
pass
def damage_player(monsters, player_state):
for m in monsters:
2021-04-15 14:25:58 +03:00
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
2021-04-12 22:11:38 +03:00
pass
2021-04-14 23:50:31 +03:00
def game_step(map, monsters, player_state, doors):
#if player_pos == door for any door ?
2021-04-13 01:20:31 +03:00
move_monsters(map, monsters)
2021-04-14 23:50:31 +03:00
damage_player(monsters, player_state)
2021-04-13 01:20:31 +03:00
pass
2021-04-12 22:11:38 +03:00
2021-04-15 14:25:58 +03:00
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]),
2021-04-16 01:35:25 +03:00
"Score: " + str(player_state[P_SCORE]),
2021-04-15 14:25:58 +03:00
"",
"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"
]
2021-04-15 00:24:44 +03:00
2021-04-15 14:25:58 +03:00
for i in range(len(info_str)):
stdscr.addstr(MAP_POS_Y - 1 + i, 0, info_str[i],
curses.color_pair(HIGHLIGHTED_COLOR))
2021-04-15 00:24:44 +03:00
2021-04-13 01:20:31 +03:00
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,
2021-04-15 14:25:58 +03:00
map[i][j][0], curses.color_pair(map[i][j][1]))
2021-04-13 01:20:31 +03:00
for m in monsters:
stdscr.addstr(m[0][1] + MAP_POS_Y, m[0][0] + MAP_POS_X,
2021-04-14 23:50:31 +03:00
MONSTER, curses.color_pair(MONSTER_COLOR))
2021-04-13 01:20:31 +03:00
2021-04-15 14:25:58 +03:00
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,
2021-04-13 01:20:31 +03:00
curses.color_pair(PLAYER_COLOR))
def input(stdscr): # not work
2021-04-14 23:50:31 +03:00
m = [0, 0]
2021-04-15 14:25:58 +03:00
key = ""
2021-04-14 23:50:31 +03:00
2021-04-13 01:20:31 +03:00
try:
key = stdscr.getkey()
2021-04-15 14:25:58 +03:00
if key == MOVE_UP_ACTION:
2021-04-13 01:20:31 +03:00
m[1] -= 1
2021-04-15 14:25:58 +03:00
elif key == MOVE_DOWN_ACTION:
2021-04-13 01:20:31 +03:00
m[1] += 1
2021-04-15 14:25:58 +03:00
elif key == MOVE_LEFT_ACTION:
2021-04-13 01:20:31 +03:00
m[0] -= 1
2021-04-15 14:25:58 +03:00
elif key == MOVE_RIGHT_ACTION:
2021-04-13 01:20:31 +03:00
m[0] += 1
except:
pass
# no input
2021-04-14 23:50:31 +03:00
2021-04-15 14:25:58 +03:00
return (m, key)
2021-04-13 01:20:31 +03:00
pass
2021-04-12 21:17:06 +03:00
2021-04-14 23:50:31 +03:00
def move_player(map, player_state, pos_change):
2021-04-15 00:24:44 +03:00
p = copy.deepcopy(player_state[0])
p[0] += pos_change[0]
p[1] += pos_change[1]
2021-04-14 23:50:31 +03:00
2021-04-15 00:24:44 +03:00
x = map[p[0]][p[1]][0]
2021-04-14 23:50:31 +03:00
2021-04-15 00:24:44 +03:00
if x != WALL:
player_state[0] = p
if x == ADD_HEALTH:
2021-04-15 14:25:58 +03:00
player_state[P_HEALTH] += 1
2021-04-15 00:24:44 +03:00
elif x == WEAPON:
2021-04-15 14:25:58 +03:00
player_state[P_WEAPON] += 1
2021-04-15 00:24:44 +03:00
elif x == GOLD:
2021-04-15 14:25:58 +03:00
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):
2021-04-16 01:35:25 +03:00
if player_state[P_WEAPON] <= 0:
return
2021-04-15 14:25:58 +03:00
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]):
2021-04-15 00:24:44 +03:00
map[p[0]][p[1]] = [EMPTY, SIMPLE_COLOR]
2021-04-16 01:35:25 +03:00
player_state[P_WEAPON] -= 1
2021-04-15 14:25:58 +03:00
else:
active_weapon.append([p, copy.deepcopy(direction)])
2021-04-16 01:35:25 +03:00
player_state[P_WEAPON] -= 1
2021-04-15 14:25:58 +03:00
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])
2021-05-29 19:39:39 +03:00
if not doors[player_state[P_ACTIVE_DOOR]]:
return
2021-04-15 14:25:58 +03:00
2021-05-29 19:39:39 +03:00
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]])
2021-04-15 14:25:58 +03:00
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
2021-04-14 23:50:31 +03:00
2021-04-12 22:11:38 +03:00
def main():
2021-04-13 01:20:31 +03:00
map_symbols = [
2021-04-15 14:25:58 +03:00
[[EMPTY, SIMPLE_COLOR], 90],
[[GOLD, GOLD_COLOR], 2],
[[WEAPON, WEAPON_COLOR], 4],
[[ADD_HEALTH, ADD_HEALTH_COLOR], 2],
[[SCORE, SCORE_COLOR], 2]
2021-04-13 01:20:31 +03:00
]
2021-04-12 22:11:38 +03:00
stdscr = begin_curses()
2021-04-15 14:25:58 +03:00
map_size = [40, 20]
2021-04-13 01:20:31 +03:00
2021-04-15 14:25:58 +03:00
active_weapon = [] # positions of active weapon
2021-04-13 01:20:31 +03:00
2021-04-12 22:11:38 +03:00
map = []
2021-04-15 14:25:58 +03:00
generate_map(map, map_size[0], map_size[1], map_symbols, 20, 100, 45)
2021-04-13 01:20:31 +03:00
doors = generate_doors(map)
2021-04-15 14:25:58 +03:00
monsters = generate_monsters(map, 100, 3)
2021-04-14 23:50:31 +03:00
2021-04-15 14:25:58 +03:00
max_score = calc_max_score(map)
player_state = [doors[0], 10, 2, 0, 0, 0]
# pos = [x, y], lives, weapon, money, active door, score
2021-04-13 01:20:31 +03:00
main_loop_exception = False
2021-04-12 22:11:38 +03:00
2021-04-15 14:25:58 +03:00
player_win = False
2021-04-13 01:20:31 +03:00
2021-04-15 14:25:58 +03:00
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
2021-04-12 22:11:38 +03:00
end_curses(stdscr)
2021-04-13 01:20:31 +03:00
if main_loop_exception:
2021-04-15 14:25:58 +03:00
print("Error during main loop")
elif player_win:
print("You win!")
else:
print("You lose(")
2021-04-13 01:20:31 +03:00
2021-05-29 19:39:39 +03:00
if (__name__ == "__main__"):
main()