-
Notifications
You must be signed in to change notification settings - Fork 3
/
mechanics.py
122 lines (101 loc) · 3.33 KB
/
mechanics.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
import yugidb as db
import card_util as cu
from playfield import *
# Phase->start effect->microphase->end effect
# Microphase stack: effect->summon/set->response->effect->...
# Rule checking for summoning a normal monster
# Includes cases for tributing summons
# Does not check if handind is valid.
def can_summon_normal(pf, player, handind):
# Check if a normal summon had already occurred for this round.
if pf.PREV_NORM_SUMMON == pf.ROUND_CNT:
return False
# Get the stats of the card
stats = db.get_card_stat(pf.HAND[player][handind]["id"])
if cu.gen_type(stats["type"]) != "monster" or int(stats["level"]) > 4:
return False
return True
# Check if can set spell or trap card
def can_set_spell(pf, player, handind):
spell_count = cu.multi_array_count(pf.SPELL[player])
pend_count = cu.multi_array_count(pf.PEND[player])
if spell_count >= 3 and pend_count >= 2:
return False
return True
# Only quick play if quick play card type.
def can_play_spell(pf, player, handind):
stat = db.get_card_stat(pf.HAND[player][handind]["id"])
if stat["race"] != "Quick-Play":
return False
return True
# Check if we can activate the spell
def can_activate_spell(pf, player, spellind):
if pf.SPELL[player][spellind][0]["roundset"] == pf.ROUND_CNT:
return False
return True
# Position functions return a dict of arrays
# Mainly for those cards that can play in more than one zone.
# e.g. spell cards
# Basic function to get available positions
def avail_summon_pos(pf, player):
avail = {"field": []}
for a in pf.FIELD[player]:
if len(pf.FIELD[player][a]) == 0:
avail["field"].append(a)
return avail
# Returns first the spell card zone followed by pend
def avail_spell_pos(pf, player):
avail = {"spell": [], "pend": []}
for a in pf.SPELL[player]:
if len(pf.SPELL[player][a]) == 0:
avail["spell"].append(a)
for a in pf.PEND[player]:
if len(pf.PEND[player][a]) == 0:
avail["pend"].append(a)
return avail
# Recall Types as listed in util:
# fusion, link, synchro, xyz, monster, spell, trap, skill
# Function to list positions to play
POS_LIST = {
"hand": {
"monster": {
"Normal Summon": avail_summon_pos,
},
"spell": {
"Set Spell": avail_spell_pos,
"Play Spell": avail_spell_pos,
},
"trap": {
"Set Trap": avail_spell_pos,
"Play Trap": avail_spell_pos,
}
}
}
# List of actions grouped by type
# also grouped by card location
MECH_LIST = {
"hand": {
"monster": {
"Normal Summon": can_summon_normal,
},
"spell": {
"Set Spell": can_set_spell,
"Play Spell": can_play_spell,
},
"trap": {
"Set Trap": can_set_spell,
"Play Trap": can_play_spell,
}
}
}
# check if the player has won
# Only check lifepoints and deck size.
def player_lose(pf, player):
if pf.LP[player] <= 0:
return True
elif len(pf.DECK[player]) == 0:
return True
return False
# Check if there is a lose state.
def lose_state(pf):
return (player_lose(pf, P1) or player_lose(pf, P2))