First commit
This commit is contained in:
commit
beb2866a32
1 changed files with 155 additions and 0 deletions
155
arshipery.py
Normal file
155
arshipery.py
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
|
||||
# Playing battleships with archery.
|
||||
# You fire two arrows, one for the column index and one for the line index.
|
||||
# The score on the target gives you the index.
|
||||
# An arrow going out of the target discards the current pair.
|
||||
|
||||
# Hypothesis:
|
||||
# – The arrow distribution on the target follow a normal law.
|
||||
# – The drift on target is symetric in all direction. There is no covariance in the distribution.
|
||||
|
||||
# Questions:
|
||||
# – Given a player's precision, what are the cells with the minimal probability of hit?
|
||||
|
||||
import sys
|
||||
import math
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def x(p):
|
||||
return p[0]
|
||||
def y(p):
|
||||
return p[1]
|
||||
def dist(u,v):
|
||||
return np.sqrt( (x(v)-x(u))*(x(v)-x(u)) + (y(v)-y(u))*(y(v)-y(u)) )
|
||||
|
||||
|
||||
def fire(nb_arrows, targeted_score, dispersion_score, dim=2):
|
||||
"""Return a numpy array of arrows coordinates the form: [[x_1, … , x_n],[y_1, …, y_n]]"""
|
||||
assert( 1 <= targeted_score <= 10)
|
||||
# Variance of 1 = almost all arrows in center.
|
||||
mean = np.zeros(nb_arrows) + (10 - targeted_score) * d_radius / math.sqrt(2)
|
||||
var = np.ones(nb_arrows) * 2*dispersion_score # FIXME var = f(disp,d_radius)
|
||||
arrows=np.random.normal(mean, var, (dim,nb_arrows))
|
||||
return arrows
|
||||
|
||||
|
||||
def make_target(nb_circles, d_radius):
|
||||
"""Return an array of circles radius ranges of he form: [(inf_10,sup_10), …, (inf_1,sup_1)]"""
|
||||
target_dist = []
|
||||
prev_r = float("inf")
|
||||
for t in np.arange( nb_circles, 0, -1 ):
|
||||
r = t*d_radius-d_radius/2
|
||||
target_dist.append((prev_r,r))
|
||||
prev_r = r
|
||||
target_dist.append((r,0))
|
||||
return target_dist
|
||||
|
||||
|
||||
def play(p1_level, p2_level, nb_circles, nb_arrows, dim = 2):
|
||||
center = np.zeros((dim,nb_arrows))
|
||||
p1,p2 = 0,1
|
||||
score = np.zeros((2,nb_arrows*nb_circles*nb_circles))
|
||||
arrows = []
|
||||
for i in range(nb_circles):
|
||||
arrows.append([None for i in range(nb_circles)])
|
||||
# The players target (i,j)
|
||||
n = 0
|
||||
for i in range(nb_circles):
|
||||
for j in range(nb_circles):
|
||||
arrows[i][j] = [ fire(nb_arrows, i+1, p1_level, dim), fire(nb_arrows, j+1, p2_level, dim) ]
|
||||
dists = [ dist(arrows[i][j][p1],center), dist(arrows[i][j][p2],center) ]
|
||||
|
||||
# Compute the scores reached by each arrow.
|
||||
for a in range(nb_arrows):
|
||||
d1 = dists[p1][a]
|
||||
d2 = dists[p2][a]
|
||||
# If at one of the arrows is out, let a score of zero for both. # FIXME option to discard zeros
|
||||
if d1 < targets[0][1] and d2 < targets[0][1]:
|
||||
# Find the reached circle and mark score.
|
||||
for k,(sup,inf) in enumerate(targets):
|
||||
if inf <= d1 < sup:
|
||||
score[p1][n] = k
|
||||
if inf <= d2 < sup:
|
||||
score[p2][n] = k
|
||||
n += 1
|
||||
|
||||
return arrows, score
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
nb_arrows = 10000
|
||||
|
||||
d_radius = 10
|
||||
dim = 2
|
||||
nb_circles = 10
|
||||
player_level = {"01-gold":1, "02-yellow":2,"04-red":5,"06-blue":9,"08-black":11,"10-white":14,"99-crap":20}
|
||||
print("levels=",sorted(player_level.keys()))
|
||||
|
||||
targets = make_target(nb_circles, d_radius)
|
||||
print("targets=",targets)
|
||||
|
||||
# One line per player level, two subplots:
|
||||
# on left, an example target, on right the density of probability.
|
||||
fig, axarr = plt.subplots(len(player_level),3)
|
||||
|
||||
|
||||
for i,pl in enumerate(sorted(player_level.keys())):
|
||||
print(i,"/",len(player_level),":",pl)
|
||||
sys.stdout.flush()
|
||||
|
||||
# DRAW TARGET
|
||||
|
||||
# Pastel
|
||||
targets_colors = ["gold","lightcoral","lightblue","lightgrey","white",]
|
||||
|
||||
# Official
|
||||
# targets_colors = ["yellow","red","blue","black","white",]
|
||||
|
||||
prev_r = 0
|
||||
for t,(inf,sup) in enumerate(targets):
|
||||
face = plt.Circle((0, 0), sup, color=targets_colors[(nb_circles-t-1)//2],zorder=2)
|
||||
border = plt.Circle((0, 0), sup, color="grey", fill=False,zorder=2)
|
||||
axarr[i,0].add_artist(face)
|
||||
axarr[i,0].add_artist(border)
|
||||
axarr[i,0].set_aspect("equal")
|
||||
|
||||
|
||||
# DRAW ARROWS
|
||||
# for i,k in enumerate(player_level.keys()):
|
||||
# arrows = fire(nb_arrows, 10-i, player_level[k])
|
||||
# axarr[0,0].scatter(*arrows, edgecolor=player_color[i], color="none", alpha=0.3, marker=".", zorder=100)
|
||||
|
||||
arrows, score = play(player_level[pl], player_level[pl], nb_circles, nb_arrows, dim)
|
||||
|
||||
|
||||
# Plot arbitrary arrows.
|
||||
aim_p1 = 1
|
||||
aim_p2 = 1
|
||||
max_points = 100
|
||||
lim = 2 * (nb_circles * d_radius)
|
||||
axarr[i,0].set_xlim((-lim,lim))
|
||||
axarr[i,0].set_ylim((-lim,lim))
|
||||
p1,p2 = 0,1
|
||||
p1_arrows = arrows[aim_p1-1][aim_p2-1][p1][:,:max_points]
|
||||
p2_arrows = arrows[aim_p1-1][aim_p2-1][p2][:,:max_points]
|
||||
axarr[i,0].scatter(* p1_arrows , edgecolor="magenta", color="none", alpha=0.3, marker=".", zorder=100)
|
||||
axarr[i,0].scatter(*(-1*p2_arrows), edgecolor="green" , color="none", alpha=0.3, marker=".", zorder=100)
|
||||
|
||||
H,xe,ye = np.histogram2d(*score, bins=11, normed=True)
|
||||
|
||||
# Plot the full normalized histogram
|
||||
axarr[i,1].imshow(H, interpolation='nearest', origin='low',
|
||||
# extent=[xe[0],xe[-1],ye[0],ye[-1]]
|
||||
# extent=[0,11,0,11]
|
||||
)
|
||||
|
||||
# Plot the normalized histogram without out arrows.
|
||||
axarr[i,2].imshow(H[1:,1:], interpolation='nearest', origin='low',
|
||||
# extent=[xe[0],xe[-1],ye[0],ye[-1]]
|
||||
# extent=[1,11,1,11]
|
||||
)
|
||||
|
||||
plt.show()
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue