able to play through a game without issues using the base set
This commit is contained in:
17
cards.py
17
cards.py
@@ -85,7 +85,7 @@ class Citizen(Card):
|
||||
worker_count, gold_payout_on_turn, gold_payout_off_turn, strength_payout_on_turn,
|
||||
strength_payout_off_turn, magic_payout_on_turn, magic_payout_off_turn, has_special_payout_on_turn,
|
||||
has_special_payout_off_turn, special_payout_on_turn, special_payout_off_turn, special_citizen,
|
||||
expansion):
|
||||
expansion, is_flipped=False):
|
||||
super().__init__()
|
||||
self.citizen_id = citizen_id
|
||||
self.name = name
|
||||
@@ -108,6 +108,7 @@ class Citizen(Card):
|
||||
self.special_payout_off_turn = special_payout_off_turn
|
||||
self.special_citizen = special_citizen
|
||||
self.expansion = expansion
|
||||
self.is_flipped = bool(is_flipped)
|
||||
|
||||
def get_special_payout_on_turn(self):
|
||||
return self.special_payout_on_turn
|
||||
@@ -115,6 +116,7 @@ class Citizen(Card):
|
||||
def to_dict(self):
|
||||
base_dict = super().to_dict()
|
||||
return {**base_dict,
|
||||
"is_flipped": bool(getattr(self, "is_flipped", False)),
|
||||
"citizen_id": self.citizen_id,
|
||||
"gold_cost": self.gold_cost,
|
||||
"roll_match1": self.roll_match1,
|
||||
@@ -164,12 +166,14 @@ class Citizen(Card):
|
||||
special_payout_on_turn=dict_["special_payout_on_turn"],
|
||||
special_payout_off_turn=dict_["special_payout_off_turn"],
|
||||
special_citizen=dict_["special_citizen"],
|
||||
expansion=dict_["expansion"])
|
||||
expansion=dict_["expansion"],
|
||||
is_flipped=bool(dict_.get("is_flipped", False)))
|
||||
|
||||
|
||||
class Domain(Card):
|
||||
def __init__(self, domain_id, name, gold_cost, shadow_count, holy_count, soldier_count, worker_count, vp_reward,
|
||||
has_activation_effect, has_passive_effect, passive_effect, activation_effect, text, expansion):
|
||||
has_activation_effect, has_passive_effect, passive_effect, activation_effect, text, expansion,
|
||||
acquired_turn_number=None):
|
||||
super().__init__()
|
||||
self.domain_id = domain_id
|
||||
self.name = name
|
||||
@@ -185,6 +189,7 @@ class Domain(Card):
|
||||
self.activation_effect = activation_effect
|
||||
self.text = text
|
||||
self.expansion = expansion
|
||||
self.acquired_turn_number = acquired_turn_number
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
@@ -208,7 +213,8 @@ class Domain(Card):
|
||||
"passive_effect": self.passive_effect,
|
||||
"activation_effect": self.activation_effect,
|
||||
"text": self.text,
|
||||
"expansion": self.expansion
|
||||
"expansion": self.expansion,
|
||||
"acquired_turn_number": getattr(self, "acquired_turn_number", None),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
@@ -227,7 +233,8 @@ class Domain(Card):
|
||||
passive_effect=dict_['passive_effect'],
|
||||
activation_effect=dict_['activation_effect'],
|
||||
text=dict_['text'],
|
||||
expansion=dict_['expansion']
|
||||
expansion=dict_['expansion'],
|
||||
acquired_turn_number=dict_.get('acquired_turn_number'),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -54,11 +54,11 @@ The server will start on `http://localhost:8000`
|
||||
```json
|
||||
{
|
||||
"player_id": "...",
|
||||
"action_type": "hire_citizen|buy_domain|slay_monster|act_on_required_action|roll_phase|harvest_phase|play_turn",
|
||||
"action_type": "hire_citizen|build_domain|slay_monster|act_on_required_action|roll_phase|harvest_phase|play_turn",
|
||||
"citizen_id": 123, // for hire_citizen
|
||||
"domain_id": 456, // for buy_domain
|
||||
"domain_id": 456, // for build_domain
|
||||
"monster_id": 789, // for slay_monster
|
||||
"gold_cost": 5, // for hire_citizen/buy_domain
|
||||
"gold_cost": 5, // for hire_citizen/build_domain
|
||||
"strength_cost": 3, // for slay_monster
|
||||
"magic_cost": 0, // optional
|
||||
"action": "choose 1" // for act_on_required_action
|
||||
|
||||
@@ -58,7 +58,7 @@ Common paths:
|
||||
|
||||
- `roll_phase()` rolls two dice and computes a sum
|
||||
- `harvest_phase()` pays out from owned starters/citizens for all players based on the roll
|
||||
- `hire_citizen(...)`, `buy_domain(...)`, `slay_monster(...)` mutate board stacks and player resources
|
||||
- `hire_citizen(...)`, `build_domain(...)`, `slay_monster(...)` mutate board stacks and player resources
|
||||
|
||||
### “choose …” actions
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ Lobby cleanup:
|
||||
Supported `action_type` values currently include:
|
||||
|
||||
- `hire_citizen`
|
||||
- `buy_domain`
|
||||
- `build_domain`
|
||||
- `slay_monster`
|
||||
- `take_resource`
|
||||
- `harvest_card`
|
||||
|
||||
90
game_models.py
Normal file
90
game_models.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from cards import Citizen, Domain, Duke, Monster, Starter
|
||||
|
||||
|
||||
class Player:
|
||||
def __init__(self, player_id, name):
|
||||
self.player_id = player_id
|
||||
self.name = name
|
||||
self.owned_starters = []
|
||||
self.owned_citizens = []
|
||||
self.owned_domains = []
|
||||
self.owned_dukes = []
|
||||
self.owned_monsters = []
|
||||
self.gold_score = 2
|
||||
self.strength_score = 0
|
||||
self.magic_score = 1
|
||||
self.victory_score = 0
|
||||
self.is_first = False
|
||||
self.shadow_count = 0
|
||||
self.holy_count = 0
|
||||
self.soldier_count = 0
|
||||
self.worker_count = 0
|
||||
self.effects = {
|
||||
"roll_phase": [],
|
||||
"harvest_phase": [],
|
||||
"action_phase": [],
|
||||
}
|
||||
self.harvest_delta = {"gold": 0, "strength": 0, "magic": 0, "victory": 0}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data):
|
||||
player_id = data["player_id"]
|
||||
name = data["name"]
|
||||
player = cls(player_id, name)
|
||||
player.owned_starters = [Starter.from_dict(s) for s in data["owned_starters"]]
|
||||
player.owned_citizens = [Citizen.from_dict(c) for c in data["owned_citizens"]]
|
||||
player.owned_domains = [Domain.from_dict(d) for d in data["owned_domains"]]
|
||||
player.owned_dukes = [Duke.from_dict(d) for d in data["owned_dukes"]]
|
||||
player.owned_monsters = [Monster.from_dict(m) for m in data["owned_monsters"]]
|
||||
player.gold_score = data["gold_score"]
|
||||
player.strength_score = data["strength_score"]
|
||||
player.magic_score = data["magic_score"]
|
||||
player.victory_score = data["victory_score"]
|
||||
player.is_first = data["is_first"]
|
||||
player.effects = data["effects"]
|
||||
player.harvest_delta = data.get("harvest_delta", {"gold": 0, "strength": 0, "magic": 0, "victory": 0})
|
||||
roles = player.calc_roles()
|
||||
player.shadow_count = roles["shadow_count"]
|
||||
player.holy_count = roles["holy_count"]
|
||||
player.soldier_count = roles["soldier_count"]
|
||||
player.worker_count = roles["worker_count"]
|
||||
return player
|
||||
|
||||
def calc_roles(self):
|
||||
shadow_count = 0
|
||||
holy_count = 0
|
||||
soldier_count = 0
|
||||
worker_count = 0
|
||||
for citizen in self.owned_citizens:
|
||||
shadow_count = shadow_count + citizen.shadow_count
|
||||
holy_count = holy_count + citizen.holy_count
|
||||
soldier_count = soldier_count + citizen.soldier_count
|
||||
worker_count = worker_count + citizen.worker_count
|
||||
for domain in self.owned_domains:
|
||||
shadow_count = shadow_count + domain.shadow_count
|
||||
holy_count = holy_count + domain.holy_count
|
||||
soldier_count = soldier_count + domain.soldier_count
|
||||
worker_count = worker_count + domain.worker_count
|
||||
roles_dict = {
|
||||
"shadow_count": shadow_count,
|
||||
"holy_count": holy_count,
|
||||
"soldier_count": soldier_count,
|
||||
"worker_count": worker_count,
|
||||
}
|
||||
return roles_dict
|
||||
|
||||
|
||||
class LobbyMember:
|
||||
def __init__(self, player_name, player_id):
|
||||
self.name = player_name
|
||||
self.player_id = player_id
|
||||
self.is_ready = False
|
||||
self.debug_starting_resources = False
|
||||
self.last_active_time = 0
|
||||
|
||||
|
||||
class GameMember:
|
||||
def __init__(self, player_id, player_name, game_id):
|
||||
self.name = player_name
|
||||
self.player_id = player_id
|
||||
self.game_id = game_id
|
||||
111
game_serialization.py
Normal file
111
game_serialization.py
Normal file
@@ -0,0 +1,111 @@
|
||||
from json import JSONEncoder
|
||||
|
||||
from cards import Citizen, Domain, Duke, Monster, Starter
|
||||
from game_models import GameMember, LobbyMember, Player
|
||||
|
||||
|
||||
class SummaryEncoder(JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, Player):
|
||||
return {
|
||||
"player_id": obj.player_id,
|
||||
"name": obj.name,
|
||||
"owned_citizens": len(obj.owned_citizens),
|
||||
"owned_domains": len(obj.owned_domains),
|
||||
"owned_monsters": len(obj.owned_monsters),
|
||||
"gold_score": obj.gold_score,
|
||||
"strength_score": obj.strength_score,
|
||||
"magic_score": obj.magic_score,
|
||||
"victory_score": obj.victory_score,
|
||||
"is_first": obj.is_first,
|
||||
}
|
||||
if isinstance(obj, LobbyMember):
|
||||
return {
|
||||
"player_name": obj.name,
|
||||
"player_id": obj.player_id,
|
||||
"is_ready": obj.is_ready,
|
||||
}
|
||||
if isinstance(obj, GameMember):
|
||||
return {
|
||||
"player_name": obj.name,
|
||||
"player_id": obj.player_id,
|
||||
}
|
||||
if hasattr(obj, "game_id") and hasattr(obj, "player_list"):
|
||||
return {
|
||||
"game_id": obj.game_id,
|
||||
"player_list": obj.player_list,
|
||||
}
|
||||
return super().default(obj)
|
||||
|
||||
|
||||
class GameObjectEncoder(JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, Player):
|
||||
roles = obj.calc_roles()
|
||||
return {
|
||||
"player_id": obj.player_id,
|
||||
"name": obj.name,
|
||||
"owned_starters": [starter.to_dict() for starter in obj.owned_starters],
|
||||
"owned_citizens": [citizen.to_dict() for citizen in obj.owned_citizens],
|
||||
"owned_domains": [domain.to_dict() for domain in obj.owned_domains],
|
||||
"owned_dukes": [duke.to_dict() for duke in obj.owned_dukes],
|
||||
"owned_monsters": [monster.to_dict() for monster in obj.owned_monsters],
|
||||
"gold_score": obj.gold_score,
|
||||
"strength_score": obj.strength_score,
|
||||
"magic_score": obj.magic_score,
|
||||
"victory_score": obj.victory_score,
|
||||
"is_first": obj.is_first,
|
||||
"shadow_count": roles["shadow_count"],
|
||||
"holy_count": roles["holy_count"],
|
||||
"soldier_count": roles["soldier_count"],
|
||||
"worker_count": roles["worker_count"],
|
||||
"effects": obj.effects,
|
||||
"harvest_delta": getattr(obj, "harvest_delta", {"gold": 0, "strength": 0, "magic": 0, "victory": 0}),
|
||||
}
|
||||
if isinstance(obj, Duke):
|
||||
return obj.to_dict()
|
||||
if isinstance(obj, Monster):
|
||||
return obj.to_dict()
|
||||
if isinstance(obj, Starter):
|
||||
return obj.to_dict()
|
||||
if isinstance(obj, Citizen):
|
||||
return obj.to_dict()
|
||||
if isinstance(obj, Domain):
|
||||
return obj.to_dict()
|
||||
if hasattr(obj, "game_id") and hasattr(obj, "player_list") and hasattr(obj, "monster_grid"):
|
||||
ca_raw = getattr(obj, "concurrent_action", None)
|
||||
ca_enc = ca_raw
|
||||
if isinstance(ca_raw, dict) and not (ca_raw.get("pending") or []):
|
||||
ca_enc = None
|
||||
return {
|
||||
"game_id": obj.game_id,
|
||||
"player_list": obj.player_list,
|
||||
"monster_grid": obj.monster_grid,
|
||||
"citizen_grid": obj.citizen_grid,
|
||||
"domain_grid": obj.domain_grid,
|
||||
"die_one": obj.die_one,
|
||||
"die_two": obj.die_two,
|
||||
"die_sum": obj.die_sum,
|
||||
"rolled_die_one": getattr(obj, "rolled_die_one", obj.die_one),
|
||||
"rolled_die_two": getattr(obj, "rolled_die_two", obj.die_two),
|
||||
"rolled_die_sum": getattr(obj, "rolled_die_sum", obj.die_sum),
|
||||
"pending_roll": getattr(obj, "pending_roll", None),
|
||||
"exhausted_count": obj.exhausted_count,
|
||||
"effects": obj.effects,
|
||||
"action_required": obj.action_required,
|
||||
"pending_required_choice": getattr(obj, "pending_required_choice", None),
|
||||
"pending_action_end_queue": getattr(obj, "pending_action_end_queue", None) or [],
|
||||
"concurrent_action": ca_enc,
|
||||
"tick_id": getattr(obj, "tick_id", 0),
|
||||
"turn_number": getattr(obj, "turn_number", 1),
|
||||
"turn_index": getattr(obj, "turn_index", 0),
|
||||
"phase": getattr(obj, "phase", "roll"),
|
||||
"actions_remaining": getattr(obj, "actions_remaining", 0),
|
||||
"active_player_id": obj.current_player_id() if hasattr(obj, "current_player_id") else None,
|
||||
"harvest_player_order": getattr(obj, "harvest_player_order", None),
|
||||
"harvest_player_idx": getattr(obj, "harvest_player_idx", 0),
|
||||
"harvest_consumed": getattr(obj, "harvest_consumed", {}) or {},
|
||||
"harvest_prompt_slots": obj.harvest_slots_for_api() if hasattr(obj, "harvest_slots_for_api") else [],
|
||||
"game_log": list(getattr(obj, "game_log", None) or []),
|
||||
}
|
||||
return super().default(obj)
|
||||
283
game_setup.py
Normal file
283
game_setup.py
Normal file
@@ -0,0 +1,283 @@
|
||||
import random
|
||||
from typing import List
|
||||
|
||||
from cards import Citizen, Domain, Duke, Monster, Starter
|
||||
from game_models import Player
|
||||
|
||||
|
||||
def load_game_data(game_id, preset, player_list_from_lobby, debug_starting_resources=False):
|
||||
import mariadb
|
||||
|
||||
monster_query = ""
|
||||
monster_stack = []
|
||||
citizen_query = ""
|
||||
citizen_stack = []
|
||||
domain_query = "select_random_domains"
|
||||
domain_stack = []
|
||||
duke_query = "select_random_dukes"
|
||||
duke_stack = []
|
||||
starter_query = "SELECT * FROM starters"
|
||||
starter_stack = []
|
||||
player_list = []
|
||||
citizen_grid: List[List[Citizen]] = [[] for _ in range(10)]
|
||||
domain_grid: List[List[Domain]] = [[] for _ in range(5)]
|
||||
monster_grid: List[List[Monster]] = [[] for _ in range(5)]
|
||||
die_one = 0
|
||||
die_two = 0
|
||||
die_sum = 0
|
||||
exhausted_count = 0
|
||||
effects = {
|
||||
"roll_phase": [],
|
||||
"harvest_phase": [],
|
||||
"action_phase": [],
|
||||
}
|
||||
action_required = {
|
||||
"id": "",
|
||||
"action": "",
|
||||
}
|
||||
tick_id = 0
|
||||
turn_number = 1
|
||||
turn_index = 0
|
||||
# Start in setup; if no setup actions are needed the engine will advance into roll.
|
||||
phase = "setup"
|
||||
actions_remaining = 0
|
||||
harvest_processed = False
|
||||
pending_harvest_choices = []
|
||||
match preset:
|
||||
case "base1":
|
||||
monster_query = "select_base1_monsters"
|
||||
citizen_query = "select_base1_citizens"
|
||||
case "base2":
|
||||
monster_query = "select_base2_monsters"
|
||||
citizen_query = "select_base2_citizens"
|
||||
try:
|
||||
my_connect = mariadb.connect(
|
||||
user="vckonline", password="vckonline", host="127.0.0.1", database="vckonline", port=3306
|
||||
)
|
||||
my_cursor = my_connect.cursor(dictionary=True)
|
||||
|
||||
my_cursor.callproc(monster_query)
|
||||
|
||||
results = my_cursor.fetchall()
|
||||
for row in results:
|
||||
my_monster = Monster(
|
||||
row["id_monsters"],
|
||||
row["name"],
|
||||
row["area"],
|
||||
row["monster_type"],
|
||||
row["monster_order"],
|
||||
row["strength_cost"],
|
||||
row["magic_cost"],
|
||||
row["vp_reward"],
|
||||
row["gold_reward"],
|
||||
row["strength_reward"],
|
||||
row["magic_reward"],
|
||||
row["has_special_reward"],
|
||||
row["special_reward"],
|
||||
row["has_special_cost"],
|
||||
row["special_cost"],
|
||||
row["is_extra"],
|
||||
row["expansion"],
|
||||
)
|
||||
monster_stack.append(my_monster)
|
||||
|
||||
my_cursor.callproc(citizen_query)
|
||||
citizen_count = 5
|
||||
if len(player_list_from_lobby) == 5:
|
||||
citizen_count = 6
|
||||
results = my_cursor.fetchall()
|
||||
for row in results:
|
||||
for _ in range(citizen_count):
|
||||
my_citizen = Citizen(
|
||||
row["id_citizens"],
|
||||
row["name"],
|
||||
row["gold_cost"],
|
||||
row["roll_match1"],
|
||||
row["roll_match2"],
|
||||
row["shadow_count"],
|
||||
row["holy_count"],
|
||||
row["soldier_count"],
|
||||
row["worker_count"],
|
||||
row["gold_payout_on_turn"],
|
||||
row["gold_payout_off_turn"],
|
||||
row["strength_payout_on_turn"],
|
||||
row["strength_payout_off_turn"],
|
||||
row["magic_payout_on_turn"],
|
||||
row["magic_payout_off_turn"],
|
||||
row["has_special_payout_on_turn"],
|
||||
row["has_special_payout_off_turn"],
|
||||
row["special_payout_on_turn"],
|
||||
row["special_payout_off_turn"],
|
||||
row["special_citizen"],
|
||||
row["expansion"],
|
||||
)
|
||||
citizen_stack.append(my_citizen)
|
||||
|
||||
my_cursor.callproc(domain_query)
|
||||
results = my_cursor.fetchall()
|
||||
for row in results:
|
||||
my_domain = Domain(
|
||||
row["id_domains"],
|
||||
row["name"],
|
||||
row["gold_cost"],
|
||||
row["shadow_count"],
|
||||
row["holy_count"],
|
||||
row["soldier_count"],
|
||||
row["worker_count"],
|
||||
row["vp_reward"],
|
||||
row["has_activation_effect"],
|
||||
row["has_passive_effect"],
|
||||
row["passive_effect"],
|
||||
row["activation_effect"],
|
||||
row["text"],
|
||||
row["expansion"],
|
||||
)
|
||||
domain_stack.append(my_domain)
|
||||
|
||||
my_cursor.callproc(duke_query)
|
||||
results = my_cursor.fetchall()
|
||||
for row in results:
|
||||
my_duke = Duke(
|
||||
row["id_dukes"],
|
||||
row["name"],
|
||||
row["gold_mult"],
|
||||
row["strength_mult"],
|
||||
row["magic_mult"],
|
||||
row["shadow_mult"],
|
||||
row["holy_mult"],
|
||||
row["soldier_mult"],
|
||||
row["worker_mult"],
|
||||
row["monster_mult"],
|
||||
row["citizen_mult"],
|
||||
row["domain_mult"],
|
||||
row["boss_mult"],
|
||||
row["minion_mult"],
|
||||
row["beast_mult"],
|
||||
row["titan_mult"],
|
||||
row["expansion"],
|
||||
)
|
||||
duke_stack.append(my_duke)
|
||||
|
||||
my_cursor.execute(starter_query)
|
||||
my_result = my_cursor.fetchall()
|
||||
for row in my_result:
|
||||
my_starter = Starter(
|
||||
row["id_starters"],
|
||||
row["name"],
|
||||
row["roll_match1"],
|
||||
row["roll_match2"],
|
||||
row["gold_payout_on_turn"],
|
||||
row["gold_payout_off_turn"],
|
||||
row["strength_payout_on_turn"],
|
||||
row["strength_payout_off_turn"],
|
||||
row["magic_payout_on_turn"],
|
||||
row["magic_payout_off_turn"],
|
||||
row["has_special_payout_on_turn"],
|
||||
row["has_special_payout_off_turn"],
|
||||
row["special_payout_on_turn"],
|
||||
row["special_payout_off_turn"],
|
||||
row["expansion"],
|
||||
)
|
||||
starter_stack.append(my_starter)
|
||||
my_cursor.close()
|
||||
my_connect.close()
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
# create players and determine order
|
||||
if not all([player_list_from_lobby, starter_query, monster_stack, citizen_stack, domain_stack, duke_stack]):
|
||||
raise ValueError("One or more required lists are empty.")
|
||||
else:
|
||||
for player in player_list_from_lobby:
|
||||
my_player = Player(player.player_id, player.name)
|
||||
if debug_starting_resources:
|
||||
my_player.gold_score = 100
|
||||
my_player.strength_score = 100
|
||||
my_player.magic_score = 100
|
||||
player_list.append(my_player)
|
||||
random.shuffle(player_list)
|
||||
player_list[0].is_first = True
|
||||
# give players starters and dukes
|
||||
for player in player_list:
|
||||
player.owned_starters.append(starter_stack[0])
|
||||
player.owned_starters.append(starter_stack[1])
|
||||
for _ in range(2):
|
||||
player.owned_dukes.append(duke_stack.pop())
|
||||
# deal monsters onto the board
|
||||
grouped_monsters = {}
|
||||
for monster in monster_stack:
|
||||
area = monster.area
|
||||
if area in grouped_monsters:
|
||||
grouped_monsters[area].append(monster)
|
||||
else:
|
||||
grouped_monsters[area] = [monster]
|
||||
for area, monsters in grouped_monsters.items():
|
||||
monsters.sort(key=lambda item: item.order, reverse=True)
|
||||
areas = list(grouped_monsters.keys())
|
||||
chosen_areas = random.sample(areas, 5)
|
||||
for i, area in enumerate(chosen_areas):
|
||||
monsters = grouped_monsters[area]
|
||||
monster_grid[i].extend(monsters)
|
||||
for stack in monster_grid:
|
||||
for monster in stack:
|
||||
monster.toggle_visibility(True)
|
||||
stack[-1].toggle_accessibility(True)
|
||||
# deal citizens onto the board
|
||||
citizens_by_roll = {roll: [] for roll in [1, 2, 3, 4, 5, 6, 7, 8, 9, 11]}
|
||||
for citizen in citizen_stack:
|
||||
citizen.toggle_visibility()
|
||||
citizens_by_roll[citizen.roll_match1].append(citizen)
|
||||
for roll in citizens_by_roll:
|
||||
index = roll - 1 if roll < 11 else 9
|
||||
citizens = citizens_by_roll[roll]
|
||||
citizen_grid[index].extend(list(citizens))
|
||||
citizen_grid[index][-1].toggle_accessibility(True)
|
||||
if debug_starting_resources:
|
||||
for player in player_list:
|
||||
for stack in citizen_grid:
|
||||
c = stack.pop(-1)
|
||||
c.is_flipped = False
|
||||
c.toggle_visibility(True)
|
||||
c.toggle_accessibility(True)
|
||||
player.owned_citizens.append(c)
|
||||
if stack:
|
||||
stack[-1].toggle_accessibility(True)
|
||||
# deal the domains into stacks
|
||||
for i in range(5):
|
||||
stack = domain_grid[i]
|
||||
for j in range(3):
|
||||
if j == 2:
|
||||
domain = domain_stack.pop()
|
||||
domain.toggle_visibility(True)
|
||||
domain.toggle_accessibility(True)
|
||||
stack.append(domain)
|
||||
else:
|
||||
domain = domain_stack.pop()
|
||||
stack.append(domain)
|
||||
|
||||
game_state = {
|
||||
"game_id": game_id,
|
||||
"player_list": player_list,
|
||||
"monster_grid": monster_grid,
|
||||
"citizen_grid": citizen_grid,
|
||||
"domain_grid": domain_grid,
|
||||
"die_one": die_one,
|
||||
"die_two": die_two,
|
||||
"die_sum": die_sum,
|
||||
"exhausted_count": exhausted_count,
|
||||
"effects": effects,
|
||||
"action_required": action_required,
|
||||
"concurrent_action": None,
|
||||
"tick_id": tick_id,
|
||||
"turn_number": turn_number,
|
||||
"turn_index": turn_index,
|
||||
"phase": phase,
|
||||
"actions_remaining": actions_remaining,
|
||||
"harvest_processed": harvest_processed,
|
||||
"pending_harvest_choices": pending_harvest_choices,
|
||||
"harvest_player_order": None,
|
||||
"harvest_player_idx": 0,
|
||||
"harvest_consumed": {},
|
||||
"game_log": [],
|
||||
"pending_action_end_queue": [],
|
||||
}
|
||||
return game_state
|
||||
@@ -1,17 +1,17 @@
|
||||
INSERT INTO vckonline.domains (name,gold_cost,shadow_count,holy_count,soldier_count,worker_count,vp_reward,has_activation_effect,has_passive_effect,passive_effect,activation_effect,`text`,image) VALUES
|
||||
('Jousting Field',13,1,0,1,1,3,0,1,NULL,NULL,'During your Harvest Phase, gain 1gp * Knight you own.',NULL),
|
||||
('Ancient Tomb',7,0,1,1,1,3,1,0,NULL,NULL,'Immediately add 3sp to a Monster Strength value.',NULL),
|
||||
('Foxgrove Palisade',9,1,0,1,0,3,0,1,NULL,NULL,'During your Roll Phase, you may pay 2gp to change one die to equal 6.',NULL),
|
||||
('The Desert Orchid',9,1,1,0,0,3,0,1,NULL,NULL,'During your Roll Phase, you may pay 1gp * owned Holy Citizens to change one die to equal 1.',NULL),
|
||||
('Pretorius Conclave',8,1,1,1,1,2,1,0,NULL,NULL,'Immediately gain a Citizen from the center stacks.',NULL),
|
||||
('Emerald Stronghold',12,0,1,1,1,5,0,1,NULL,NULL,'During your Action phase, ignore ''+'' when buying Citizens.',NULL),
|
||||
('Pratchett''s Plateau',8,0,1,0,1,3,0,1,NULL,NULL,'During your Action phase, Domains cost you 1gp less to buy.',NULL),
|
||||
('Shelly Commons',13,0,1,1,1,4,0,1,NULL,NULL,'At the end of your Action phase, pay 1gp to a Player of your choice to gain 1vp.',NULL),
|
||||
('Cathedral of St Aquila',8,0,2,0,0,3,0,1,NULL,NULL,'At the end of your Action phase, take 1gp from a Player of your choice.',NULL),
|
||||
('Cursed Cavern',10,1,1,0,1,2,1,0,NULL,NULL,'All players immediately flip a Citizen and you gain 4mp.',NULL);
|
||||
('Jousting Field',13,1,0,1,1,3,0,1,'harvest:gain_per_owned_citizen_name Knight g 1',NULL,'During your Harvest Phase, gain 1gp * Knight you own.',NULL),
|
||||
('Ancient Tomb',7,0,1,1,1,3,1,0,NULL,'activation_monster_strength +3','Immediately add 3sp to a Monster Strength value.',NULL),
|
||||
('Foxgrove Palisade',9,1,0,1,0,3,0,1,'roll:set_one_die target=6 cost=g:2',NULL,'During your Roll Phase, you may pay 2gp to change one die to equal 6.',NULL),
|
||||
('The Desert Orchid',9,1,1,0,0,3,0,1,'roll:set_one_die target=1 cost=g_per_owned_role:holy_citizen',NULL,'During your Roll Phase, you may pay 1gp * owned Holy Citizens to change one die to equal 1.',NULL),
|
||||
('Pretorius Conclave',8,1,1,1,1,2,1,0,NULL,'choose <citizens>','Immediately gain a Citizen from the center stacks.',NULL),
|
||||
('Emerald Stronghold',12,0,1,1,1,5,0,1,'effect:add action:emeraldstronghold',NULL,'During your Action phase, ignore ''+'' when buying Citizens.',NULL),
|
||||
('Pratchett''s Plateau',8,0,1,0,1,3,0,1,'effect:add action:pratchettsplateau',NULL,'During your Action phase, Domains cost you 1gp less to build.',NULL),
|
||||
('Shelley Commons',13,0,1,1,1,4,0,1,'action:end manipulate_resources mode=pay_to_player gain=vp:1 pay=g:1 optional=true',NULL,'At the end of your Action phase, pay 1gp to a Player of your choice to gain 1vp.',NULL),
|
||||
('Cathedral of St Aquila',8,0,2,0,0,3,0,1,'action:end manipulate_resources mode=take_from_player take=g:1 optional=true',NULL,'At the end of your Action phase, take 1gp from a Player of your choice.',NULL),
|
||||
('Cursed Cavern',10,1,1,0,1,2,1,0,NULL,'m 4 + concurrent_flip_one_citizen','All players immediately flip a Citizen and you gain 4mp.',NULL);
|
||||
INSERT INTO vckonline.domains (name,gold_cost,shadow_count,holy_count,soldier_count,worker_count,vp_reward,has_activation_effect,has_passive_effect,passive_effect,activation_effect,`text`,image) VALUES
|
||||
('Darktide Harbour',6,1,0,1,1,2,1,0,NULL,NULL,'Immediately gain a Shadow Citizen from the center stacks.',NULL),
|
||||
('King Tower',12,0,1,0,2,3,0,1,NULL,NULL,'At the end of your Action Phase, pay 1mp to a Player of your choice to gain 1vp.',NULL),
|
||||
('Cloudrider''s Camp',8,0,1,1,0,2,1,0,NULL,NULL,'Immediately gain 3sp and a Soldier Citizen worth 2gp or less.',NULL),
|
||||
('The Orb of Urdr',6,1,1,0,0,1,0,1,NULL,NULL,'At the end of your Action Phase, take 1mp from a Player of your choice.',NULL),
|
||||
('Wisborg',6,1,0,0,2,3,1,0,NULL,NULL,'You may immediately pay 3gp to gain 3vp.',NULL);
|
||||
('Darktide Harbour',6,1,0,1,1,2,1,0,NULL,'choose <citizens where role==shadow>','Immediately gain a Shadow Citizen from the center stacks.',NULL),
|
||||
('King Tower',12,0,1,0,2,3,0,1,'action:end manipulate_resources mode=pay_to_player gain=vp:1 pay=m:1 optional=true',NULL,'At the end of your Action Phase, pay 1mp to a Player of your choice to gain 1vp.',NULL),
|
||||
('Cloudrider''s Camp',8,0,1,1,0,2,1,0,NULL,'s 3 + choose <citizens where role==soldier and gold_cost<=2>','Immediately gain 3sp and a Soldier Citizen worth 2gp or less.',NULL),
|
||||
('The Orb of Urdr',6,1,1,0,0,1,0,1,'action:end manipulate_resources mode=take_from_player take=m:1 optional=true',NULL,'At the end of your Action Phase, take 1mp from a Player of your choice.',NULL),
|
||||
('Wisborg',6,1,0,0,2,3,1,0,NULL,'manipulate_resources mode=self_convert pay=g:3 gain=vp:3 optional=true','You may immediately pay 3gp to gain 3vp.',NULL);
|
||||
|
||||
Reference in New Issue
Block a user