@@ -12,9 +12,9 @@ import ( | |||
"time" | |||
) | |||
var stars[] models.Star | |||
var flights[] models.Flight | |||
var links[] models.Link | |||
var stars []models.Star | |||
var flights []models.Flight | |||
var links []models.Link | |||
func main() { | |||
// Write to logfile | |||
@@ -23,7 +23,7 @@ func main() { | |||
rand.Seed(10000) | |||
filename := fmt.Sprintf("logs/%d.txt", r1.Intn(10000)) | |||
f, err := os.Create(filename) | |||
if err != nil{ | |||
if err != nil { | |||
panic(err) | |||
} | |||
defer f.Close() | |||
@@ -31,19 +31,19 @@ func main() { | |||
// Open stdin for reading | |||
reader := bufio.NewReader(os.Stdin) | |||
var gameComplete bool =false | |||
var roundComplete bool =false | |||
var gameComplete bool = false | |||
var roundComplete bool = false | |||
// Run strategy | |||
strategy := strategies.SimpleStrategy {} | |||
strategy := strategies.SimpleStrategy{} | |||
//strategy := strategies.NoneStrategy {} | |||
for gameComplete == false { | |||
roundComplete = false | |||
// Empty flights | |||
flights = [] models.Flight{} | |||
links = [] models.Link{} | |||
flights = []models.Flight{} | |||
links = []models.Link{} | |||
for roundComplete == false { | |||
text, err := reader.ReadString('\n') | |||
if err != nil { | |||
@@ -79,9 +79,9 @@ func parseLine(text string) bool { | |||
X: x, | |||
Y: y, | |||
Richness: 0, | |||
Owner: -2, | |||
Ships: -2, | |||
Turns: -2, | |||
Owner: -2, | |||
Ships: -2, | |||
Turns: -2, | |||
} | |||
stars = append(stars, star) | |||
} | |||
@@ -102,7 +102,7 @@ func parseLine(text string) bool { | |||
var source_idx, _ = strconv.Atoi(parts[1]) | |||
var target_idx, _ = strconv.Atoi(parts[2]) | |||
link := models.Link { | |||
link := models.Link{ | |||
SourceStar: source_idx, | |||
TargetStar: target_idx, | |||
} | |||
@@ -116,7 +116,7 @@ func parseLine(text string) bool { | |||
var owner, _ = strconv.Atoi(parts[4]) | |||
var turns, _ = strconv.Atoi(parts[5]) | |||
flight := models.Flight { | |||
flight := models.Flight{ | |||
SourceStar: source_idx, | |||
TargetStar: target_idx, | |||
Ships: ship_count, |
@@ -22,3 +22,19 @@ type Link struct { | |||
SourceStar int | |||
TargetStar int | |||
} | |||
func (s *Star) Unowned() bool { | |||
return s.Owner < 0 | |||
} | |||
func (s *Star) OwnedByMe() bool { | |||
return s.Owner == 0 | |||
} | |||
func (s *Star) Friendly() bool { | |||
return s.Owner == 1 | |||
} | |||
func (s *Star) Enemy() bool { | |||
return s.Owner == 2 | |||
} |
@@ -0,0 +1,33 @@ | |||
package strategies | |||
import ( | |||
"botg/models" | |||
"math" | |||
) | |||
type StarAffiliation int | |||
const ( | |||
Own StarAffiliation = 0 | |||
Friend StarAffiliation = 1 | |||
Enemy StarAffiliation = 2 | |||
) | |||
func flightTurnDistance(x, y int, star *models.Star) int { | |||
pointDistance := distanceBetweenPoints(x, y, star.X, star.Y) | |||
if pointDistance == 0 { | |||
return 0 | |||
} | |||
return int(math.Ceil(pointDistance / 10)) | |||
} | |||
func distanceBetweenPoints(x1, y1, x2, y2 int) float64 { | |||
// Is it the same point? The distance is defined as 0 | |||
if x1 == x2 && y1 == y2 { | |||
return 0 | |||
} | |||
return math.Sqrt(math.Pow(float64(x1-x2), 2) + math.Pow(float64(y1-y2), 2)) | |||
} |
@@ -0,0 +1,100 @@ | |||
package strategies | |||
import ( | |||
"botg/models" | |||
"fmt" | |||
) | |||
type LinkerStrategy struct { | |||
} | |||
func (ls *LinkerStrategy) Execute(stars []models.Star, flights []models.Flight, links []models.Link) { | |||
friendly := make([]int, 10) | |||
friendlyDistanceMatrix := make(map[models.Star]map[models.Star]int) | |||
for i, s := range stars { | |||
// Skip unowned and enemy stars | |||
if s.Unowned() || s.Enemy() { | |||
continue | |||
} | |||
// Keep track of own stars | |||
if s.OwnedByMe() || s.Friendly() { | |||
friendly = append(friendly, i) | |||
} | |||
friendlyDistanceMatrix[s] = make(map[models.Star]int) | |||
} | |||
// Keep a map of all the distances | |||
for i := 0; i < len(friendly); i++ { | |||
src := stars[i] | |||
for j := i + 1; j < len(friendly); j++ { | |||
dst, flightDistance := stars[j], 0 | |||
if src.Idx == dst.Idx { | |||
// Shouldn't happen, but oh well | |||
continue | |||
} | |||
if ls.linkedOrInProgress(&src, &dst, links, flights) { | |||
continue | |||
} | |||
flightDistance = flightTurnDistance(src.X, src.Y, &dst) | |||
friendlyDistanceMatrix[src][dst] = flightDistance | |||
} | |||
} | |||
top3Picks := []struct { | |||
src *models.Star | |||
dst *models.Star | |||
distance int | |||
}{ | |||
{nil, nil, 300 * 300}, | |||
{nil, nil, 300 * 300}, | |||
{nil, nil, 300 * 300}, | |||
} | |||
for src, dstmap := range friendlyDistanceMatrix { | |||
for dst, distance := range dstmap { | |||
for i := 0; i < len(top3Picks); i++ { | |||
if top3Picks[i].src == nil { | |||
top3Picks[i].src = &src | |||
top3Picks[i].dst = &dst | |||
break | |||
} | |||
if distance < top3Picks[i].distance { | |||
top3Picks[i].src = &src | |||
top3Picks[i].dst = &dst | |||
} | |||
} | |||
} | |||
} | |||
fmt.Println("done") | |||
} | |||
func (s *LinkerStrategy) insufficientShipsForLinking(star *models.Star) bool { | |||
return star.Ships < 5 | |||
} | |||
func (s *LinkerStrategy) linkedOrInProgress(src *models.Star, dst *models.Star, links []models.Link, flights []models.Flight) bool { | |||
linking := false | |||
for _, l := range links { | |||
if (l.SourceStar == src.Idx && l.TargetStar == dst.Idx) || (l.SourceStar == dst.Idx && l.TargetStar == src.Idx) { | |||
linking = true | |||
break | |||
} | |||
} | |||
for _, f := range flights { | |||
if (f.SourceStar == src.Idx && f.TargetStar == dst.Idx) || (f.SourceStar == dst.Idx && f.TargetStar == src.Idx) { | |||
linking = true | |||
break | |||
} | |||
} | |||
return linking | |||
} |
@@ -6,10 +6,8 @@ import ( | |||
) | |||
type NoneStrategy struct { | |||
} | |||
func (s NoneStrategy) Execute(stars[] models.Star, flights[] models.Flight, links[] models.Link) { | |||
func (s NoneStrategy) Execute(stars []models.Star, flights []models.Flight, links []models.Link) { | |||
fmt.Println("done") | |||
} | |||
@@ -3,15 +3,13 @@ package strategies | |||
import ( | |||
"botg/models" | |||
"fmt" | |||
"math" | |||
) | |||
type SimpleStrategy struct { | |||
} | |||
func (s *SimpleStrategy) Execute(stars[] models.Star, flights[] models.Flight, links[] models.Link) { | |||
func (s *SimpleStrategy) Execute(stars []models.Star, flights []models.Flight, links []models.Link) { | |||
for i, s := range stars { | |||
// Maximum flights per star per round is 3 | |||
total := 0 | |||
@@ -56,13 +54,13 @@ func (s *SimpleStrategy) Execute(stars[] models.Star, flights[] models.Flight, l | |||
// If enemy star, make sure we have enough ships to attack it | |||
//if t.Owner == 2 && (s.Ships - (t.Ships + (flightTurnDistance * t.Richness))) <= 1 { | |||
if t.Owner == 2 && (s.Ships/2) - (t.Ships + (6 * t.Richness)) < 0 { | |||
if t.Owner == 2 && (s.Ships/2)-(t.Ships+(6*t.Richness)) < 0 { | |||
continue | |||
} | |||
// TODO: Find best destination | |||
// Fly to this target, and skip processing all remaining potential target stars | |||
fmt.Printf("fly %d %d %d\n", i, j, s.Ships / 2) | |||
fmt.Printf("fly %d %d %d\n", i, j, s.Ships/2) | |||
total++ | |||
break | |||
} | |||
@@ -83,7 +81,7 @@ func calculateDistanceCeiling(source *models.Star, target *models.Star) int { | |||
ub := 300 * 2 | |||
for lb < ub { | |||
mb := (lb + ub) / 2 | |||
if mb * mb >= squareDist { | |||
if mb*mb >= squareDist { | |||
ub = mb | |||
} else { | |||
lb = mb + 1 | |||
@@ -92,22 +90,3 @@ func calculateDistanceCeiling(source *models.Star, target *models.Star) int { | |||
return lb | |||
} | |||
func flightTurnDistance(x, y int, star *models.Star) int { | |||
pointDistance := distanceBetweenPoints(x, y, star.X, star.Y) | |||
if pointDistance == 0 { | |||
return 0 | |||
} | |||
return int(math.Ceil(pointDistance / 10)) | |||
} | |||
func distanceBetweenPoints(x1, y1, x2, y2 int) float64 { | |||
// Is it the same point? The distance is defined as 0 | |||
if x1 == x2 && y1 == y2 { | |||
return 0 | |||
} | |||
return math.Sqrt(math.Pow(float64(x1 - x2), 2) + math.Pow(float64(y1 - y2), 2)) | |||
} |