-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathginkgopolis.py
118 lines (102 loc) · 4.33 KB
/
ginkgopolis.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
import asyncio
import random
from board import Board, MARKERS, TILES
from cards import MarkerCard, card_factory, Planter, Scientist, Architect, Mechanic, Clerk
from constants import RED, YELLOW, BLUE, ORANGE, WHITE, VICTORY_POINT, RESOURCE, TILE, BUILD_UP
from pieces import Tile
from player import RandomPlayer
class GameController():
def __init__(self, players):
self.heroes = [
[Planter(), Scientist(), Architect()],
[Mechanic(), Clerk(), Architect()]
]
self.tile_pool = [Tile(RED, number) for number in range(4, 21)] + \
[Tile(YELLOW, number) for number in range(4, 21)] + \
[Tile(BLUE, number) for number in range(4, 21)]
self.draw_pile = [MarkerCard(marker) for marker in MARKERS] + \
[card_factory(tile) for tile in TILES]
self.discard_pile = []
for _set in (self.tile_pool, self.draw_pile, self.heroes):
random.shuffle(_set)
self.board = Board()
self.players = players
for player, heroes in zip(self.players, self.heroes):
player.board = self.board
player.game_controller = self
player.cards = heroes
for hero in heroes:
for starter in hero.starting:
if starter == VICTORY_POINT:
player.victory_points += 1
elif starter == RESOURCE:
player.resources += 1
elif starter == TILE:
player.give_tile(self.draw_tile())
self.draw_cards()
self.first_player = random.randrange(len(self.players) + 1)
async def play_round(self):
actions = await asyncio.wait([player.plan_action() for player in self.players])
planned_actions = {}
for action in actions[0]:
player, kind, card, extra = action.result()
player.pay_for_move(kind, card, extra)
if kind != BUILD_UP:
self.discard_pile.append(card)
planned_actions[player] = (kind, extra)
self._execute_planned_actions(planned_actions)
self.prepare_next_round()
print(self.board)
print("Discarded cards: {}".format(self.discard_pile))
print("Cards to draw: {}".format(len(self.draw_pile)))
print("Tiles left: {}".format(len(self.tile_pool)))
print()
for player in self.players:
print(player)
print()
print("======================================")
return {player.name: action for player, action in planned_actions.items()}
def _execute_planned_actions(self, planned_actions):
for player in (self.players[self.first_player:] + self.players[:self.first_player]):
kind, extra = planned_actions[player]
print("{}'s move: {} ({})".format(player.name, kind, extra))
changes = getattr(self.board, kind.lower())(**extra)
player.action_executed(changes)
def prepare_next_round(self):
self.rotate_hands()
self.draw_cards()
def rotate_hands(self):
hands = []
for player in self.players:
hands.append(player.hand)
for idx, hand in enumerate(hands):
self.players[(idx + 1) % len(self.players)].hand = hand
def draw_cards(self):
for player in self.players:
while len(player.hand) < 4:
player.hand.append(self.draw_pile.pop())
if not self.draw_pile:
self.refresh_draw_pile()
def draw_tile(self):
try:
return self.tile_pool.pop()
except IndexError:
return None
def refresh_draw_pile(self):
self.draw_pile = self.discard_pile[:]
self.discard_pile = []
while self.board.new_tiles:
new_tile = self.board.new_tiles.pop()
self.draw_pile.append(card_factory(new_tile))
random.shuffle(self.draw_pile)
def game_over(self):
return not self.tile_pool
async def main():
john = RandomPlayer('John', ORANGE)
amanda = RandomPlayer('Amanda', WHITE)
game_controller = GameController([john, amanda])
while not game_controller.game_over():
await game_controller.play_round()
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())