import matplotlib.pyplot as plt
from matplotlib.patches import RegularPolygon
import matplotlib.patches as mpatches
import numpy as np
import scipy.stats as stat
import random
sums = list(range(2,13))
prob_dict = {}
for s in sums:
prob_dict[s] = 0
for i in range(1,7):
for j in range(1,7):
prob_dict[i+j] += 1
for k in prob_dict.keys():
prob_dict[k] = prob_dict[k]/36
prob_dict[0] = 0
prob_dict
import math
class tile(object):
def __init__(self, x, y, r, value, resource, id):
self.x = x
self.y = y
self.r = r
self.value = value
self.resource = resource
self.id = id
class point(object):
def __init__(self, x, y, r, id):
self.x = x
self.y = y
self.r = r
self.tiles = []
self.id = id
self.resource_dict = {}
y_shift = r/2
x_shift = r/2*np.sqrt(3)
self.neighbors = [[self.x-x_shift, self.y+y_shift], [self.x+x_shift, self.y+y_shift], [self.x, self.y-y_shift],
[self.x, self.y+y_shift], [self.x-x_shift, self.y-y_shift], [self.x+x_shift, self.y-y_shift]]
self.neighbor_point_ids = []
def next_to(self, tile, buffer=0.45):
for i in range(len(self.neighbors)):
temp = self.neighbors[i]
if abs(temp[0]-tile.x)<buffer and abs(temp[1]-tile.y)<buffer:
return True
return False
def add_tile(self, tile ):
self.tiles = self.tiles + [tile]
t_resource = tile.resource
if t_resource in self.resource_dict.keys():
self.resource_dict[t_resource] += prob_dict[tile.value]
else:
self.resource_dict[t_resource] = prob_dict[tile.value]
def get_value(self):
temp = 0
for k in self.resource_dict.keys():
temp += self.resource_dict[k]
return temp
def create_board_layout(a,b,r):
widths = list(range(a,b+1,1)) + list(range(b-1,a-1,-1))
hieghts = list(range(len(widths)))
n = sum(widths)
y_shift = r/2
x_shift = r/2*np.sqrt(3)
x_points = []
y_points = []
tiles = []
count = 0
for i in range(len(widths)):
w = widths[i]
left = (max(widths) - w)/2
for j in range(w):
count += 1
t = tile(j+left, i, r, None, None, count)
tiles.append(t)
# upper left
x_points.append(j + left - x_shift)
y_points.append(i + y_shift)
# upper
x_points.append(j + left)
y_points.append(i + r)
# upper right
x_points.append(j + left + x_shift)
y_points.append(i + y_shift)
if i <= len(widths)/2:
# lower left
x_points.append(0 + left - x_shift)
y_points.append(i - y_shift)
# lower right
x_points.append(w - 1 + left + x_shift)
y_points.append(i - y_shift)
# Last Row
w = min(widths)
for j in range(w):
# lower
x_points.append(j + left)
y_points.append(0 - r)
# lower left
x_points.append(j + left - x_shift)
y_points.append(0 - y_shift)
return tiles, x_points, y_points, n
def draw_board(tiles, r_map, r_labels):
fig, ax = plt.subplots(1, figsize=(12,12))
ax.set_facecolor("#cfdfff")
for i in range(n):
t = tiles[i]
# Draw Tile
hexagon = RegularPolygon((t.x, t.y), numVertices=6, radius=r, alpha=1, edgecolor='black', facecolor=r_map[t.resource])
ax.text(t.x, t.y, t.value)
ax.text(t.x-0.1, t.y - 0.1, str(prob_dict[values[i]])[:5] )
ax.add_patch(hexagon)
plt.autoscale(enable = True)
patches = []
for j in range(len(r_labels)):
patches.append(mpatches.Patch(facecolor=r_map[j], label=r_labels[j], edgecolor="black"))
ax.legend(handles=patches)
return fig, ax
def create_points(tiles, x_points, y_points, r):
# Create Points
points = []
point_values = []
count = 0
for i in range(m):
p = point(x_points[i], y_points[i], r, count)
points.append(p)
for t in tiles:
if p.next_to(t):
p.add_tile(t)
#plt.plot([p.x,t.x],[p.y, t.y])
point_values.append(p.get_value())
count += 1
# Find Neighboring Points
for i in range(m):
p = points[i]
for p2 in points:
if p.next_to(p2):
if (p.x == p2.x and p.y == p2.y) == False:
p.neighbor_point_ids.append(p2.id)
return points
def draw_points(points, ranks):
for i in range(len(points)):
p = points[i]
plt.scatter(p.x, p.y, s=1500*p.get_value(), c ="orange", edgecolors="black", zorder=10)
ax.text(p.x-0.05, p.y-0.05, int(ranks[i]) , zorder=15)
def deep_value(points, max_d):
m = len(points)
deep_point_values = np.zeros((m, max_d))
for j in range(d):
# iterate through points
for i in range(m):
p = points[i]
if j == 0:
deep_point_values[i,j] = p.get_value()
else:
temp = deep_point_values[i,j-1]
for id in p.neighbor_point_ids:
temp += points[id].get_value()*gamma**j
deep_point_values[i,j] = temp
return deep_point_values
def draw_connections(p, ids=None, w=[], color="lightpink"):
if ids == None:
ids = p.neighbor_point_ids
for i in range(len(ids)):
pi = points[ids[i]]
if len(w) == 0:
plt.plot([pi.x, p.x], [pi.y, p.y], color=color, linewidth=10)
else:
plt.plot([pi.x, p.x], [pi.y, p.y], color=color, linewidth=w[i]*20)
def best_path(points, deep_point_values, d, l, start=None):
m = len(points)
seen = []
if start == None:
ranks = m - stat.rankdata(deep_point_values[:, d], method='min')
best_i = np.argmin(ranks)
else:
best_i = start
seen.append(best_i)
pi = points[best_i]
for i in range(l):
options = pi.neighbor_point_ids
for o in options:
if o in seen:
options.remove(o)
neighbor_values = deep_point_values[options, d]
best_i = pi.neighbor_point_ids[np.argmax(neighbor_values)]
pi = points[best_i]
seen.append(best_i)
return seen
def draw_path(seen, color):
for i in range(1, len(seen)):
id1 = seen[i-1]
id2 = seen[i]
p1 = points[id1]
p2 = points[id2]
plt.plot([p1.x, p2.x], [p1.y, p2.y], color=color, linewidth=10*(1 - i/len(seen)))
# Set Up Board
r = 1/np.sqrt(3)
gamma = 0.8 # discount factor
tiles, x_points, y_points, n = create_board_layout(3, 5, r)
m = len(x_points)
# Randomly Assign Values
all_nums = [2,2,3,3,4,4,5,5,6,6,8,8,9,9,10,10,11,11,12]
values = random.sample(all_nums, n) #np.random.randint(2, 12, size=n)
# Randomly Assign Resources
# Wheat, Wood, Sheep, Stone, Brick, Desert
all_resources = [0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,4,4,4,5]
resources = random.sample(all_resources, n) #np.random.randint(4, size=n)
r_labels = ["Wheat", "Wood", "Sheep", "Stone", "Brick", "Desert"]
r_map = ["#fcba03", "darkgreen", "#56a870", "#919090","#cc4331", "white"]
for i in range(n):
t = tiles[i]
t.resource = resources[i]
t.value = values[i]
points = create_points(tiles, x_points, y_points, r)
deep_point_values = deep_value(points, 10)
ranks = m - stat.rankdata(deep_point_values[:, 0], method='min')
seen = best_path(points, deep_point_values, 0, 10)
print(seen)
fig, ax = draw_board(tiles, r_map, r_labels)
draw_points(points, ranks)
best_i = np.argmin(ranks)
best_p = points[best_i]
draw_connections(best_p)
# for id in seen:
# draw_connections(points[id])
draw_path(seen, color="#96037e")
plt.show()
plt.show()
fig, ax = draw_board(tiles, r_map, r_labels)
draw_points(points, ranks)
deep_point_values = deep_value(points, 10)
seen = best_path(points, deep_point_values, 0, 20)
print(seen)
# for id in seen:
# draw_connections(points[id])
draw_path(seen, color="#96037e")
plt.show()
import pandas as pd
import seaborn as sns
vdf = pd.DataFrame(deep_point_values)
vdf.style.background_gradient(cmap ='coolwarm')