-
-
Notifications
You must be signed in to change notification settings - Fork 52
/
gameexample.py
102 lines (85 loc) · 3.41 KB
/
gameexample.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
import itertools
import sys
from curtsies import FullscreenWindow, Input, FSArray
from curtsies.fmtfuncs import red, bold, green, on_blue, yellow, on_red
class Entity:
def __init__(self, display, x, y, speed=1):
self.display = display
self.x, self.y = x, y
self.speed = speed
def towards(self, entity):
dx = entity.x - self.x
dy = entity.y - self.y
return vscale(self.speed, (sign(dx), sign(dy)))
def die(self):
self.speed = 0
self.display = on_red(bold(yellow('o')))
def sign(n):
return -1 if n < 0 else 0 if n == 0 else 1
def vscale(c, v):
return tuple(c*x for x in v)
class World:
def __init__(self, width, height):
self.width = width
self.height = height
n = 5
self.player = Entity(on_blue(green(bold('5'))), width // 2, height // 2 - 2, speed=5)
self.npcs = [Entity(on_blue(red('X')), i * width // (n * 2), j * height // (n * 2))
for i in range(1, 2*n, 2)
for j in range(1, 2*n, 2)]
self.turn = 0
entities = property(lambda self: self.npcs + [self.player])
def move_entity(self, entity, dx, dy):
entity.x = max(0, min(self.width-1, entity.x + dx))
entity.y = max(0, min(self.height-1, entity.y + dy))
def process_event(self, c):
"""Returns a message from tick() to be displayed if game is over"""
if c == "":
sys.exit()
elif c in key_directions:
self.move_entity(self.player, *vscale(self.player.speed, key_directions[c]))
else:
return "try arrow keys, w, a, s, d, or ctrl-D (you pressed %r)" % c
return self.tick()
def tick(self):
"""Returns a message to be displayed if game is over, else None"""
for npc in self.npcs:
self.move_entity(npc, *npc.towards(self.player))
for entity1, entity2 in itertools.combinations(self.entities, 2):
if (entity1.x, entity1.y) == (entity2.x, entity2.y):
if self.player in (entity1, entity2):
return 'you lost on turn %d' % self.turn
entity1.die()
entity2.die()
if all(npc.speed == 0 for npc in self.npcs):
return 'you won on turn %d' % self.turn
self.turn += 1
if self.turn % 20 == 0:
self.player.speed = max(1, self.player.speed - 1)
self.player.display = on_blue(green(bold(str(self.player.speed))))
def get_array(self):
a = FSArray(self.height, self.width)
for entity in self.entities:
a[self.height - 1 - entity.y, entity.x] = entity.display
return a
key_directions = {'<UP>': (0, 1),
'<LEFT>': (-1, 0),
'<DOWN>': (0,-1),
'<RIGHT>': (1, 0),
'w': (0, 1),
'a': (-1, 0),
's': (0,-1),
'd': (1, 0)}
def main():
with FullscreenWindow(sys.stdout) as window:
with Input(sys.stdin) as input_generator:
world = World(width=window.width, height=window.height)
window.render_to_terminal(world.get_array())
for c in input_generator:
msg = world.process_event(c)
if msg:
break
window.render_to_terminal(world.get_array())
print(msg)
if __name__ == '__main__':
main()