-
Notifications
You must be signed in to change notification settings - Fork 3
/
game.py
141 lines (117 loc) · 4.04 KB
/
game.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
import random
import card_util as cu
from playfield import *
from mechanics import *
from actions import *
from collections import defaultdict
class Game:
# Number of cards to draw at the start
start_draw = 5
# Who starts first?
pfirst = P1
psec = P2
# Who is the current player
cur_player = -1
# Default Dictionary to hold actions.
actions = {}
# keeps track of reaction
# -1 means no reaction
# 0 means a reaction is in progress
# 1 means a reaction is returned without a reactions
react = 0
# Playfield variables
pf = Playfield()
# Constructor
def __init__(self):
# Pick a random character to start
if random.randint(0, 1) == 0:
self.pfirst = P1
self.psec = P2
else:
self.pfirst = P2
self.psec = P1
self.cur_player = self.pfirst
# function to check what are some actions we can take.
# Actions are grouped per field section per card, then action index.
def gen_actions(self):
# Clear the actions list.
self.actions = defaultdict(lambda: defaultdict( lambda: defaultdict(int)))
# Do the HAND deck first
# Optimization: Grab the spell cards
# TODO: Automate this field specification
org = cu.group_card_type(self.pf.HAND[self.cur_player])
for typ in org.keys():
self._gen_specific_action("hand", typ, org[typ])
return dict(self.actions)
# Play a specific action given by gen_actions
# Play action with a specific orientation
# Play action at specific position if applicable
def play_action(self, act, face = FACE_UP_ATK, pos=0):
if act != None:
# Play the action
params = act[1]
params[0](self.pf, params[1], params[2], pos, face)
if self.react == 0:
self.react = 1
else:
# Increase our reaction count
if self.react != 0:
self.react += 1
# No one has played twice in a row, remove our toggles
# otherwise, toggle and end
if self.react == 3 or self.react == 0:
self.react = 0
# Resolve our stack
resolve_stack(self.pf)
else:
self.toggle_player()
def is_reponse(self):
return (self.react != 0)
# toggle player
def toggle_player(self):
if self.cur_player == P1:
self.cur_player = P2
else:
self.cur_player = P1
# Start the game by drawing cards
def start(self):
# Draw multiple times.
for i in range(0, self.start_draw):
draw(self.pf, P1)
draw(self.pf, P2)
# Commit the actions
resolve_stack(self.pf)
# function to return available options
def next(self):
actions = self.gen_actions()
return actions
#
# Exposed functions for ease of use for bot
#
def is_lose(self):
"""Checks game is in lose state for current playing player."""
return lose_state(self.pf)
def game_over(self):
"""Checks if game is over"""
return len(self.gen_actions) == 0
#
# Private Functions
#
def _gen_specific_action(self, fro, typ, cardind):
"""Helper function for gen_action to generate type list."""
for rule, func in MECH_LIST[fro][typ].items():
for ind in cardind:
if func(self.pf, self.cur_player, ind):
# Get available positions
pos = POS_LIST[fro][typ][rule]
# Create a callable system
# does not encode available positions
params = (ACTION_LIST[fro][typ][rule], self.cur_player, ind, pos)
self.actions[fro][self.pf.HAND[self.cur_player][ind]["name"]][rule] = (rule, params)
# Iteration functions for ease of use.
def __iter__(self):
return self
def __next__(self):
if lose_state(self.pf):
raise StopIteration
return self.next()