Skip to content

Commit

Permalink
Merge pull request #50 from bcollazo/fix/bugs
Browse files Browse the repository at this point in the history
Improvements
  • Loading branch information
bcollazo committed Nov 11, 2020
2 parents e15a43b + c9d07c5 commit b61652e
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 84 deletions.
19 changes: 13 additions & 6 deletions catanatron/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import Iterable
from collections import namedtuple, defaultdict

from catanatron.algorithms import longest_road
from catanatron.algorithms import longest_road, largest_army
from catanatron.models.map import BaseMap
from catanatron.models.board import Board, BuildingType
from catanatron.models.board_initializer import Node
Expand Down Expand Up @@ -144,7 +144,7 @@ def play_tick(self, action_callback=None):
)

actions = self.playable_actions(player, action_prompt)
action = player.decide(self.board, actions)
action = player.decide(self, actions)
self.execute(action, action_callback=action_callback)

def playable_actions(self, player, action_prompt):
Expand Down Expand Up @@ -371,9 +371,12 @@ def current_player(self):
return self.players[self.current_player_index]

def count_victory_points(self):
(color, path) = longest_road(self.board, self.players, self.actions)
# TODO: Count largest army
road_color = longest_road(self.board, self.players, self.actions)[0]
army_color = largest_army(self.players, self.actions)[0]

for player in self.players:
player.has_road = False
player.has_army = False
for player in self.players:
public_vps = 0
public_vps += len(
Expand All @@ -382,8 +385,12 @@ def count_victory_points(self):
public_vps += 2 * len(
self.board.get_player_buildings(player.color, BuildingType.CITY)
) # count cities
if color != None and self.players_by_color[color] == player:
public_vps += 2
if road_color != None and self.players_by_color[road_color] == player:
public_vps += 2 # road
player.has_road = True
if army_color != None and self.players_by_color[army_color] == player:
public_vps += 2 # army
player.has_army = True

player.public_victory_points = public_vps
player.actual_victory_points = public_vps + player.development_deck.count(
Expand Down
2 changes: 2 additions & 0 deletions catanatron/models/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ def __init__(self, color, name=None):
self.resource_deck = ResourceDeck()
self.development_deck = DevelopmentDeck()
self.played_development_cards = DevelopmentDeck()
self.has_road = False
self.has_army = False

self.clean_turn_state()

Expand Down
27 changes: 16 additions & 11 deletions database.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
SELECT pickle_data FROM game_states
WHERE game_id = %s ORDER BY action_index DESC LIMIT 1
"""
SELECT_GAME_IDS_QUERY = """SELECT DISTINCT game_id FROM game_states"""
SELECT_GAME_IDS_QUERY = """SELECT game_id FROM game_states GROUP BY game_id ORDER BY MAX(id) DESC LIMIT %s"""
SELECT_STATES_QUERY = """SELECT * FROM game_states WHERE game_id = %s"""

connection = psycopg2.connect(
Expand All @@ -50,11 +50,17 @@
def save_game_state(game):
state = json.dumps(game, cls=GameEncoder)
pickle_data = pickle.dumps(game, pickle.HIGHEST_PROTOCOL)
cursor.execute(
INSERT_STATE_QUERY,
(game.id, len(game.actions), state, pickle_data),
)
connection.commit()
try:
cursor.execute(
INSERT_STATE_QUERY,
(game.id, len(game.actions), state, pickle_data),
)
connection.commit()
except (Exception, psycopg2.DatabaseError) as error:
print(
"Error in transction Reverting all other operations of a transction ", error
)
connection.rollback()


def get_last_game_state(game_id):
Expand All @@ -69,12 +75,11 @@ def get_last_game_state(game_id):


# TODO: Filter by winners
def get_finished_games_ids():
cursor.execute(SELECT_GAME_IDS_QUERY)
row = cursor.fetchone()
while row is not None:
def get_finished_games_ids(limit=10):
cursor.execute(SELECT_GAME_IDS_QUERY, (limit,))
rows = cursor.fetchall()
for row in rows:
yield row[0]
row = cursor.fetchone()


def get_game_states(game_id):
Expand Down
6 changes: 3 additions & 3 deletions play.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@


@click.command()
@click.option("--num", default=5, help="Number of greetings.")
def simulate(num):
@click.option("-n", "--number", default=5, help="Number of games.")
def simulate(number):
"""Simple program simulates NUM Catan games."""
player_classes = [WeightedRandomPlayer, RandomPlayer, RandomPlayer, SimplePlayer]
colors = [Color.RED, Color.BLUE, Color.ORANGE, Color.WHITE]
pseudonyms = ["Foo", "Bar", "Baz", "Qux"]

wins = defaultdict(int)
for x in range(num):
for x in range(number):
seating = random.sample(range(4), 4)
players = [player_classes[i](colors[i], pseudonyms[i]) for i in seating]

Expand Down
7 changes: 5 additions & 2 deletions ui/src/pages/Board.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ export default function Board({ state }) {
size = w / SQRT3;
h = 2 * size;
} else {
h = (4 * (boardHeight / numLevels)) / 3;
// boardHeight = numLevels * (3h/4) + (1h/4)
// 4*boardHeight = numLevels * 3h + 1h
// 4*boardHeight = (3*numLevels + 1)*h, so:
h = (4 * boardHeight) / (3 * numLevels + 1);
size = h / 2;
w = SQRT3 * size;
}
Expand Down Expand Up @@ -93,7 +96,7 @@ export default function Board({ state }) {
);

return (
<div className="board-container w-full flex-grow m-10">
<div className="board-container flex-grow flex">
<div ref={ref} className="board relative w-full h-full">
{tiles}
{roads}
Expand Down
52 changes: 4 additions & 48 deletions ui/src/pages/ControlPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import styled from "styled-components";

const Panel = styled.div`
height: 300px;
height: 180px;
padding: 20px;
background: white;
Expand All @@ -12,41 +12,13 @@ const Panel = styled.div`
border-top-left-radius: 40px;
`;

const CardsContainer = styled.div`
display: flex;
justify-content: center;
`;

const Card = styled.div`
width: 100px;
height: 160px;
background: white;
border-radius: 8px;
border: 1px solid #ddd;
display: flex;
margin: 0px 8px;
`;

const InnerCard = styled.div`
background: #ddd;
margin: 8px;
border-radius: 8px;
width: 100%;
`;

const ActionContainer = styled.div`
display: flex;
justify-content: center;
margin-top: 20px;
`;

const Button = styled.div`
background: #ddd;
border-radius: 8px;
padding: 10px 32px;
margin: 8px;
font-size: 1.2em;
width: 200px;
width: 300px;
text-align: center;
cursor: pointer;
user-select: none;
Expand All @@ -55,24 +27,8 @@ const Button = styled.div`
export function ControlPanel({ onClickNext, onClickAutomation }) {
return (
<Panel>
<CardsContainer>
<Card>
<InnerCard />
</Card>
<Card>
<InnerCard />
</Card>
<Card>
<InnerCard />
</Card>
<Card>
<InnerCard />
</Card>
</CardsContainer>
<ActionContainer>
<Button onClick={onClickNext}>Tick</Button>
<Button onClick={onClickAutomation}>Toggle Automation</Button>
</ActionContainer>
<Button onClick={onClickNext}>Tick</Button>
<Button onClick={onClickAutomation}>Toggle Automation</Button>
</Panel>
);
}
21 changes: 10 additions & 11 deletions ui/src/pages/GamePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ export default function GamePage() {
};

useEffect(() => {
const interval = setInterval(() => {
const interval = setInterval(async () => {
if (automation && !inFlightRequest) {
onClickNext();
await onClickNext();
}
}, 300);
}, 100);
return () => clearInterval(interval);
}, [automation, inFlightRequest]);

Expand All @@ -46,16 +46,15 @@ export default function GamePage() {
return <div></div>;
}
return (
<div className="h-full flex flex-col">
<div className="w-full h-full flex bg-blue-600">
<div className="h-full flex">
<div className="w-full h-full flex flex-col bg-blue-600">
<Board state={state} />
<SidePanel state={state} />
<ControlPanel
onClickNext={onClickNext}
onClickAutomation={onClickAutomation}
/>
</div>

<ControlPanel
onClickNext={onClickNext}
onClickAutomation={onClickAutomation}
/>
<SidePanel state={state} />
</div>
);
}
16 changes: 13 additions & 3 deletions ui/src/pages/SidePanel.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useEffect, useRef } from "react";
import cn from "classnames";

export default function SidePanel({ state }) {
const actionRef = useRef(null);
Expand Down Expand Up @@ -39,22 +40,31 @@ export default function SidePanel({ state }) {
({
color,
resource_deck,
development_deck,
public_victory_points,
actual_victory_points,
played_development_cards,
has_army,
has_road,
}) => {
const colorClass = `bg-white bg-${color.toLowerCase()}-700 h-24`;
const playerClass = `bg-white bg-${color.toLowerCase()}-700 h-42 overflow-auto`;
return (
<div key={color} className={colorClass}>
<div key={color} className={playerClass}>
<div>{JSON.stringify(resource_deck, null, 2)}</div>
<div>{JSON.stringify(development_deck, null, 2)}</div>
<div>VPs: {public_victory_points}</div>
<div>AVPs: {actual_victory_points}</div>
<div className={cn({ "font-bold": has_army })}>
Knights: {played_development_cards["KNIGHT"]}
</div>
{has_road && <div className="font-bold">Longest Road</div>}
</div>
);
}
);

return (
<div className="h-full lg:w-1/3 w-1/2 bg-gray-900 p-6">
<div className="h-full w-1/2 bg-gray-900 p-4">
<div ref={actionRef} className="h-64 overflow-auto">
{actions}
</div>
Expand Down

0 comments on commit b61652e

Please sign in to comment.