-
Notifications
You must be signed in to change notification settings - Fork 0
/
arcana_peak.py
345 lines (282 loc) · 9.66 KB
/
arcana_peak.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
#!/usr/bin/env python
"""Arcana Peak."""
import json
import logging
import os
import sys
import time
import blessed
import cmd2
os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1"
import pygame
# Global vars
term = blessed.Terminal()
chars = {}
logging.basicConfig(filename="debug.log", level=logging.DEBUG)
class Character:
"""Represent a character and its status."""
def __init__(self, status, is_npc=False):
self.status = status
self.is_npc = is_npc
print_slow("Character spawned. Please kindly welcome " +
self.status["name"] + " into the world!")
def __str__(self):
"""String."""
return str(self.status)
@property
def icon(self):
"""Icon."""
return "[O]"
def save_to_json(self):
"""Save to a JSON file."""
with open(os.path.join("chars", self.status["name"] + ".json"), "w") as file:
file.write(json.dumps(self.status))
def char_from_json(self, file):
"""Import a character from a JSON file."""
with open(file) as file:
char = json.load(file)
self.status = char
def move(self, grid, loc):
"""Move the character to the desired location on the given grid."""
grid.move(self, loc)
class Grid: # Will be replaced with a hex grid.
"""A grid for the game world."""
def __init__(self, dims):
self.dims = dims
self.entities = {}
self.empty = "[ ]"
self.squares = [[self.empty] * self.dims[1] for i in range(self.dims[0])]
def __str__(self):
"""String."""
rep = " "
for j in range(self.dims[1]):
rep += " " + str(j) + " "
for i in range(self.dims[0]):
rep += "\n" + str(i) + " "
for j in range(self.dims[1]):
rep += self.squares[i][j]
return rep
def move(self, char, loc, place=True):
"""
Move a character on the grid.
Parameters
----------
char : Character
Character that will be moved.
loc : Tuple
Location to which the character will be moved.
place : bool, optional
Determines if the character is placed if it isn't already placed.
Returns
-------
None.
"""
if char in self.entities:
current_loc = self.entities[char]
self.squares[current_loc[0]][current_loc[1]] = self.empty
if char in self.entities or place:
self.squares[loc[0]][loc[1]] = char.icon
self.entities[char] = loc
def clear(confirm=True):
"""Clear the console window after an optional user confirmation."""
if confirm:
input("\nPress enter to continue.")
print(term.clear)
def print_slow(text="", speed=0.025, new_line=True,
is_input=False, skip=True):
"""
Slowly print text across the screen, mimicking manually typed text.
Parameters
----------
text: str
The text that will be printed.
speed: float, optional
The amount of time, in seconds, spent asleep between characters
with extra time spent on certain punctuation and at the end.
The default is 0.025
new_line: bool, optional
Determines if the printing should begin on a new line.
The default is True.
is_input: bool, optional
Determines if the slow print behaves like the input function,
except with the prompt being given in a slowly printed fashion.
The default is False.
skip: bool, optional
Determines if the player is able to skip the rest of slow
printing by pressing space.
The default is True.
"""
for i, char in enumerate(text):
if char in [" ", ",", ".", ":", ";", "!", "?"]:
time.sleep(speed * 3)
sys.stdout.write(char)
sys.stdout.flush()
if skip:
with term.cbreak():
val = term.inkey(timeout=speed)
if val == " ":
sys.stdout.write(text[i + 1:])
sys.stdout.flush()
break
else:
time.sleep(speed)
time.sleep(speed * 10)
if is_input:
return input()
if new_line:
print()
def end():
"""End the game."""
print("Game terminated.")
print(term.exit_fullscreen)
sys.exit()
def snarky_quit(message):
"""Quit the game upon too many failed attempts to create a character."""
clear(confirm=False)
print_slow(message[:15] + "...\n")
time.sleep(3)
print_slow("You know what?")
time.sleep(1)
# actually I have all day, I had the time to program this message
print_slow("I don't have all day.")
time.sleep(1)
print_slow("Maybe this game just isn't for you.")
time.sleep(5)
end()
def char_name():
"""Allow the player to choose a name."""
clear(confirm=False)
failure_text = """I am just asking whether that is your name!
It really isn't that hard of a question.
A mere yes or no will suffice."""
confirm = "no"
attempts = 0
allowed_failures = 5
name = None
while confirm.lower() != "yes":
if attempts == allowed_failures:
snarky_quit(failure_text)
break
name = print_slow("Now I must ask, who are you? ", is_input=True)
confirm = print_slow("So you are " + name + "? ", is_input=True)
if confirm.lower() not in ("yes", "no"):
print_slow(failure_text)
attempts += 1
clear(confirm=False)
return name
def char_creation():
"""
Allow the player to create a character.
Returns
-------
Character
The character that the player created.
"""
play_music("theme.mid")
print_slow("Welcome to character creation.")
clear()
name = char_name()
# return the character the player created
return Character({"name": name,
"attributes": None,
"xp": None,
"hp": None,
"inventory": [],
"alignment": None,
"class": None,
"race": None,
"talents": []})
def intro():
"""Intro."""
play_music("intro.mid")
intro_text()
clear()
def intro_text():
"""Intro text."""
game_credits()
world_build()
def game_credits():
"""Introduce the game, game's creator, and licenses."""
print_slow("Welcome to Arcana Peak: The RPG")
print_slow("Arcana Peak: The RPG code is licensed under "
f"{term.link('https://www.gnu.org/licenses/gpl-3.0.en.html', 'GNU GPL v3')}.")
print_slow("Arcana Peak: The RPG Soundtrack by Dane Campbell "
"is licensed under "
f"{term.link('https://creativecommons.org/licenses/by-nc-sa/4.0/', 'CC BY-NC-SA 4.0')}.")
clear()
def world_build():
"""World build."""
print_slow("You are tasked with adventuring "
"through these lands as you see fit.")
print_slow("Among the methods available to you are "
"arcana, might, and diplomacy.")
print_slow()
print_slow("To the north, the two Human Kingdoms do little but bicker.")
print_slow("To the south, the reclusive Ek call the barren desert home.")
print_slow("In the central mountains, the Arcanists research...")
def play_music(music):
"""
Play a music file.
Parameters
---------
music: str
The name of the music file to be played.
"""
pygame.mixer.music.load("music/" + music)
pygame.mixer.music.play()
parser = cmd2.Cmd2ArgumentParser()
parser.add_argument("char", help="Character that will be moved.")
parser.add_argument("loc", help="Location to move to.")
parser2 = cmd2.Cmd2ArgumentParser()
parser2.add_argument("char", help="Character whose inventory to check.")
class GameShell(cmd2.Cmd):
"""Game shell."""
def __init__(self, grid):
super().__init__()
self.intro = "Type help or ? to list commands."
self.file = None
self.grid = grid
self._set_prompt()
self.register_postcmd_hook(self.postcmd_hook_method)
def postcmd_hook_method(self, data: cmd2.plugin.PostcommandData) -> cmd2.plugin.PostcommandData:
"""
Parameters
----------
data
Returns
-------
"""
clear()
self._set_prompt()
return data
def _set_prompt(self):
"""Set prompt."""
self.prompt = str(self.grid) + "\nState your wish: "
@cmd2.decorators.with_argparser(parser)
def do_move(self, opts):
"""Move a character to a location on the grid."""
if opts.char in chars:
chars[opts.char].move(self.grid, tuple(map(int, opts.loc.split(","))))
else:
print("Sorry, that character does not exist.")
@cmd2.decorators.with_argparser(parser2)
def do_inventory(self, opts):
"""Check inventory."""
if opts.char in chars:
print("Inventory does not work yet.")
else:
print("Sorry, that character does not exist.")
def main():
"""Run main."""
print(term.enter_fullscreen)
pygame.init()
intro()
player = char_creation()
chars[player.status["name"]] = player
player.save_to_json()
grid1 = Grid([10, 10])
clear()
GameShell(grid1).cmdloop()
end()
if __name__ == "__main__":
main()