arshipery/arshipery.py
2017-06-05 15:38:14 +02:00

155 lines
5.4 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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()