Asci/asci_lib.py

278 lines
9.0 KiB
Python
Raw Normal View History

2021-11-24 21:27:05 +01:00
# Asci (version 1.5.4)
2021-11-02 08:51:14 +01:00
2021-08-13 17:32:55 +02:00
class Screen:
2021-08-14 22:27:07 +02:00
def __init__(self, screen_width=21, screen_height=6):
2021-08-13 17:32:55 +02:00
# Screen configuration
self.screen_width = screen_width
self.screen_height = screen_height
self._data = [[" " for _ in range(screen_width)] for _ in range(screen_height)]
def clear(self):
print("\n" * self.screen_height)
def set_world(self, world):
self._world = [[char for char in line] for line in world.split("\n")[1:]]
self.map_width = max([len(line) for line in self._world])
self.map_height = len(self._world)
def set_data(self, coords):
x, y = coords
for x_map in range(x, x + self.screen_width):
for y_map in range(y, y + self.screen_height):
self._data[y_map - y][x_map - x] = " "
if 0 <= x_map < self.map_width and 0 <= y_map < self.map_height:
try: self._data[y_map - y][x_map - x] = self._world[y_map][x_map]
except: pass
def set_cell(self, x, y, value):
self._data[y][x] = value
def display(self, return_input=True):
for line in self._data:
print("".join(line))
if return_input: return input(">")
def display_text(self, string):
2021-08-23 17:21:26 +02:00
paragraphs = [i for i in text_formater(string) if i]
nb_par = len(paragraphs)
for index in range(nb_par):
self.clear()
print(paragraphs[index])
if index + 1 == nb_par: return input(">")
else: input()
2021-08-13 17:32:55 +02:00
def get_cell(self, x, y):
return self._data[y][x]
def get_map_size(self):
return self.map_width, self.map_height
class Asci:
2021-11-02 08:51:14 +01:00
def __init__(self, maps, events_mapping, keys_mapping, screen_width=21, screen_height=6):
2021-08-22 13:57:49 +02:00
# Load maps
2021-08-30 16:35:28 +02:00
self.maps = [Map(*i) for i in maps]
2021-08-13 17:32:55 +02:00
2021-08-13 22:32:36 +02:00
# Custom functions
2021-08-25 22:56:21 +02:00
self.legend = list(events_mapping.keys())
self._game_events_mapping = [events_mapping[i] for i in self.legend]
2021-11-12 16:31:33 +01:00
self._game_keys_mapping = {key: keys_mapping[key] for key in keys_mapping if not key in (1, 2, 3, 5)}
2021-08-13 22:32:36 +02:00
2021-08-22 13:57:49 +02:00
# Screen initialisation
2021-08-14 22:27:07 +02:00
self.screen = Screen(screen_width, screen_height)
2021-08-13 17:32:55 +02:00
2021-08-13 22:32:36 +02:00
def _looked_case(self, direction):
# Left
if direction == 1:
2021-08-14 17:13:34 +02:00
return self.data[2] + 9, self.data[3] + 3
2021-08-13 22:32:36 +02:00
# Right
elif direction == 3:
2021-08-14 17:13:34 +02:00
return self.data[2] + 11, self.data[3] + 3
2021-08-13 22:32:36 +02:00
# Up
elif direction == 5:
2021-08-14 17:13:34 +02:00
return self.data[2] + 10, self.data[3] + 2
2021-08-13 22:32:36 +02:00
# Down
elif direction == 2:
2021-08-14 17:13:34 +02:00
return self.data[2] + 10, self.data[3] + 4
2021-08-13 22:32:36 +02:00
2021-08-14 17:13:34 +02:00
return self.data[2] + 10, self.data[3] + 3
2021-08-13 17:32:55 +02:00
def _cell_test(self, direction):
if direction == 1:
if self.data[-2] + 9 < 0: return -1
else: cell = self.screen.get_cell(9, 3)
if direction == 3:
if self.data[-2] + 11 >= self.map_width: return -1
else: cell = self.screen.get_cell(11, 3)
if direction == 5:
if self.data[-1] + 2 < 0: return -1
else: cell = self.screen.get_cell(10, 2)
if direction == 2:
if self.data[-1] + 4 >= self.map_height: return -1
else: cell = self.screen.get_cell(10, 4)
2021-08-22 13:57:49 +02:00
cell_patterns = self.legend
2021-08-13 17:32:55 +02:00
for pattern_index in range(len(cell_patterns)):
2021-08-25 22:56:21 +02:00
if cell in cell_patterns[pattern_index]: return pattern_index
2021-08-13 17:32:55 +02:00
return -1
2021-08-13 17:32:55 +02:00
def _keyboard(self, key):
2021-08-25 22:56:21 +02:00
# Interaction while moving
2021-08-13 17:32:55 +02:00
if key in (1, 3, 5, 2):
cell_test = self._cell_test(key)
# Change map
if cell_test == len(self.legend) - 2: # or (self.data[1] and cell_test < 0):
2021-08-14 17:13:34 +02:00
self.data[1], self.data[2], self.data[3] = self._get_map(key)
self.screen.set_world(self.maps[self.data[1]].map_data)
2021-08-15 17:27:58 +02:00
self.map_width, self.map_height = self.screen.get_map_size()
2021-08-13 17:32:55 +02:00
2021-08-25 22:56:21 +02:00
# Move
elif cell_test == len(self.legend) - 1:
2021-08-25 22:56:21 +02:00
if key == 1: self.data[2] -= 1
if key == 3: self.data[2] += 1
if key == 5: self.data[3] -= 1
if key == 2: self.data[3] += 1
2021-08-13 17:32:55 +02:00
2021-08-25 22:56:21 +02:00
# Interaction
elif cell_test >= 0: self._interaction(key, cell_test)
2021-08-13 17:32:55 +02:00
2021-08-25 22:56:21 +02:00
# Custom functions
elif key in self._game_keys_mapping:
2021-08-15 17:27:58 +02:00
self.screen.clear()
self._game_keys_mapping[key](self.data, self.stat)
2021-08-15 17:27:58 +02:00
2021-08-13 17:32:55 +02:00
# Quit
2021-08-15 17:27:58 +02:00
elif key == 9:
2021-08-13 17:32:55 +02:00
self.screen.clear()
2021-08-25 22:56:21 +02:00
def _interaction(self, direction, cell_content):
2021-08-13 22:32:36 +02:00
x, y = self._looked_case(direction)
2021-11-12 16:31:33 +01:00
data_copy = [self.data[0], self.data[1], x, y]
2021-08-13 22:32:36 +02:00
2021-08-25 22:56:21 +02:00
# Get the event
2021-11-12 16:31:33 +01:00
event = self._game_events_mapping[cell_content](data_copy, self.stat)
2021-08-22 17:08:16 +02:00
2021-08-30 15:11:55 +02:00
# data modification
2021-11-12 16:31:33 +01:00
self.data[0] = data_copy[0]
if self.data[1] != data_copy[1]:
self.data[1] = data_copy[1]
self.screen.set_world(self.maps[self.data[1]].map_data)
self.map_width, self.map_height = self.screen.get_map_size()
if data_copy[2] != x: self.data[2] = data_copy[2] - 10
if data_copy[3] != y: self.data[3] = data_copy[3] - 3
2021-11-14 18:22:30 +01:00
if not event: return
event = read_event(self.data[0], event)
2021-08-14 17:13:34 +02:00
# XP and stat modification
self.data[0] += event.xp_earned
2021-08-30 15:11:55 +02:00
for index, value in event.stat:
self.stat[index] += value
2021-08-14 17:13:34 +02:00
2021-08-25 22:56:21 +02:00
# Display and get answer
if event.text:
2021-11-13 19:52:21 +01:00
answer_selected = convert(self.screen.display_text(event.text), True)
2021-11-20 13:48:34 +01:00
if event.answer and (0 < answer_selected <= event.answer):
self.data[0] += answer_selected
self._interaction(direction, cell_content)
2021-08-13 22:32:36 +02:00
def _get_map(self, direction):
2021-08-30 16:35:28 +02:00
current_coords = self._looked_case(direction)
2021-08-14 17:13:34 +02:00
current_map = self.data[1]
2021-08-13 17:32:55 +02:00
2021-08-30 16:35:28 +02:00
for coords in self.maps[current_map].coords:
if coords[:2] == current_coords:
return coords[2], coords[3] - 10, coords[4] - 3
2021-08-13 17:32:55 +02:00
2021-08-14 17:13:34 +02:00
return current_map, self.data[2], self.data[3]
2021-08-13 17:32:55 +02:00
2021-11-11 15:00:45 +01:00
def mainloop(self, end_game, stat=None, data=None, routine=None, player="@", door="^", walkable=" ", exit_key=9):
2021-11-12 16:31:33 +01:00
if exit_key in self._game_keys_mapping:
2021-11-13 19:52:21 +01:00
raise ValueError("'{}' is already assigned to a function.".format(exit_key))
2021-11-12 16:31:33 +01:00
2021-08-22 13:57:49 +02:00
# Load save ; data = [XP, map_id, x, y]
if not stat or type(stat) != list: self.stat = [100]
else: self.stat = stat
2021-08-22 13:57:49 +02:00
2021-11-11 15:00:45 +01:00
if not data: self.data = [0, 0, 0, 0]
else: self.data = [data[0], data[1], data[2] - 10, data[3] - 3]
2021-08-25 22:56:21 +02:00
self.legend.append(door)
self.legend.append(walkable)
2021-08-22 13:57:49 +02:00
# Screen and map configuration
self.screen.set_world(self.maps[data[1]].map_data)
2021-08-22 13:57:49 +02:00
self.map_width, self.map_height = self.screen.get_map_size()
2021-08-13 17:32:55 +02:00
key = key_buffer = 0
2021-08-22 13:57:49 +02:00
while key != exit_key and self.stat[0] > 0 and self.data[0] < end_game:
2021-08-13 17:32:55 +02:00
self.screen.set_data(self.data[-2:])
2021-08-25 22:56:21 +02:00
self.screen.set_cell(10, 3, player)
2021-08-13 17:32:55 +02:00
key = convert(self.screen.display())
if not key: key = key_buffer
else: key_buffer = key
self._keyboard(key)
2021-10-31 21:28:48 +01:00
2021-11-02 08:51:14 +01:00
# Launching the game routine
if routine: routine(self.data, self.stat)
2021-08-13 17:32:55 +02:00
2021-08-22 17:08:16 +02:00
if self.stat[0] <= 0: self.stat[0] = 100
2021-11-11 15:02:32 +01:00
self.data[2] += 10
self.data[3] += 3
2021-08-14 22:39:30 +02:00
return self.stat, self.data
2021-08-13 17:32:55 +02:00
2021-08-14 17:13:34 +02:00
class Event:
def __init__(self, xp_earned, text, answer=0, *stat):
self.xp_earned = xp_earned
self.text = text
self.answer = answer
self.stat = stat
class Map:
2021-08-30 16:35:28 +02:00
def __init__(self, map_data, *coords):
self.map_data = map_data
2021-08-30 16:35:28 +02:00
self.coords = coords
2021-11-13 19:52:21 +01:00
def convert(string, force_int=False):
2021-08-13 17:32:55 +02:00
try: return int(string)
2021-11-13 19:52:21 +01:00
except:
if force_int: return 0
else: return string
2021-08-13 17:32:55 +02:00
def text_formater(string, screen_width=21, screen_height=6):
def line_formater(string, screen_width):
if len(string) <= screen_width: return string
stop_index = screen_width
while stop_index > 0 and not string[stop_index].isspace(): stop_index -= 1
if not stop_index: stop_index = screen_width
return string[:stop_index] + "\n" + line_formater(string[stop_index + 1:], screen_width)
def paragraph_formater(lines, screen_height):
if len(lines) < screen_height: return "\n".join(lines)
return "\n".join(lines[:screen_height]) + "\n\n" + paragraph_formater(lines[screen_height:], screen_height)
2021-08-23 00:18:18 +02:00
lines = []
for line in string.split("\n"):
for formated_line in line_formater(line, screen_width).split("\n"):
lines.append(formated_line)
2021-08-13 17:32:55 +02:00
return paragraph_formater(lines, screen_height).split("\n\n")
2021-08-14 17:13:34 +02:00
def read_event(xp, event):
if type(event) == dict:
if xp in event: event = event[xp]
else: event = event["base"]
if type(event) != list:
raise TypeError("event is of type {} instead of list".format(type(event)))
return Event(*event)
def print_text(text):
for i in text_formater(text):
2021-11-24 21:27:05 +01:00
if not i: continue
print("\n" * 7)
print(i)
input()