better weighing function for Codes; simple bug avoidance heuristic
This commit is contained in:
parent
dc6308e364
commit
005d2a3ab6
6 changed files with 410 additions and 73 deletions
172
bofa/.ipynb_checkpoints/Calculations-checkpoint.ipynb
Normal file
172
bofa/.ipynb_checkpoints/Calculations-checkpoint.ipynb
Normal file
File diff suppressed because one or more lines are too long
141
bofa/Calculations.ipynb
Normal file
141
bofa/Calculations.ipynb
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,3 +1,9 @@
|
||||||
bot.zip: src/main/scala/bot/*.scala
|
release:
|
||||||
cd src/main/scala/bot && sed -i 's/Boolean = true/Boolean = false/' DebugUtil.scala
|
cd src/main/scala/bot && sed -i 's/Dbg: Boolean = true/Dbg: Boolean = false/' DebugUtil.scala
|
||||||
|
cd src/main/scala/bot && sed -i 's/Dbg: Boolean = false/Dbg: Boolean = true/' DebugUtil.scala
|
||||||
|
cd src/main/scala && zip -r bot bot && mv bot.zip $(CURDIR)
|
||||||
|
|
||||||
|
dbg:
|
||||||
|
cd src/main/scala/bot && sed -i 's/Dbg: Boolean = false/Dbg: Boolean = true/' DebugUtil.scala
|
||||||
|
cd src/main/scala/bot && sed -i 's/Dbg: Boolean = true/Dbg: Boolean = false/' DebugUtil.scala
|
||||||
cd src/main/scala && zip -r bot bot && mv bot.zip $(CURDIR)
|
cd src/main/scala && zip -r bot bot && mv bot.zip $(CURDIR)
|
||||||
|
|
|
@ -5,7 +5,6 @@ import DebugUtil.{log,dbg,time}
|
||||||
|
|
||||||
object Main {
|
object Main {
|
||||||
def main(args: Array[String]) = {
|
def main(args: Array[String]) = {
|
||||||
|
|
||||||
var input: String = ""
|
var input: String = ""
|
||||||
|
|
||||||
//Initialize general game settings
|
//Initialize general game settings
|
||||||
|
@ -20,12 +19,14 @@ object Main {
|
||||||
log("init cortex")
|
log("init cortex")
|
||||||
val cortex = new Cortex()
|
val cortex = new Cortex()
|
||||||
|
|
||||||
log("init debug")
|
var tmpRound = currentState.round
|
||||||
DebugUtil.state = Some(currentState)
|
|
||||||
|
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
while (input != null ){
|
while (input != null ){
|
||||||
|
if (tmpRound != currentState.round){
|
||||||
|
tmpRound = currentState.round
|
||||||
|
log("\n");
|
||||||
|
log(s"********** ROUND ${tmpRound} **********")
|
||||||
|
}
|
||||||
def cmd: Seq[String] = input.split(" ")
|
def cmd: Seq[String] = input.split(" ")
|
||||||
|
|
||||||
// dispatch
|
// dispatch
|
||||||
|
|
|
@ -24,8 +24,9 @@ class Cortex {
|
||||||
def move(state: State, time: Int): Direction = {
|
def move(state: State, time: Int): Direction = {
|
||||||
val directions: Seq[Direction] = possibleDirections(state.bofaField, state)
|
val directions: Seq[Direction] = possibleDirections(state.bofaField, state)
|
||||||
|
|
||||||
val weightBoard = weightCodes(1000, decr, state)
|
val weightBoard = weightCodes(1000, weigh, state)
|
||||||
preventFallBack(weightBoard, state)
|
preventFallBack(weightBoard, state)
|
||||||
|
preventLethal(weightBoard, state)
|
||||||
|
|
||||||
val dir = getMaxDir(state.bofaField, directions, weightBoard, state)
|
val dir = getMaxDir(state.bofaField, directions, weightBoard, state)
|
||||||
|
|
||||||
|
@ -37,18 +38,17 @@ class Cortex {
|
||||||
dir
|
dir
|
||||||
}
|
}
|
||||||
|
|
||||||
def decr(dist: Int, start: Int) = {
|
def weigh(start: Int, dist: Int, cur: Int) = {
|
||||||
val d = (start/math.pow(2.5, (dist+1))).intValue()
|
(start / math.pow(1.3, (dist + 1))).intValue()
|
||||||
if (d < 5) 5 else d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def getMaxField(weightBoard: Array[Array[Int]], state: State): Field = {
|
def getMaxField(weightBoard: Array[Array[Int]], state: State): Field = {
|
||||||
var maxField = (0,0)
|
var maxField = (0, 0)
|
||||||
for (x <- 0 until S.width; y <- 0 until S.height) {
|
for (x <- 0 until S.width; y <- 0 until S.height) {
|
||||||
// generally, the highest is best
|
// generally, the highest is best
|
||||||
if (weightBoard(x)(y) > weightBoard(maxField _1)(maxField _2)) maxField = (x,y)
|
if (weightBoard(x)(y) > weightBoard(maxField _1)(maxField _2)) maxField = (x, y)
|
||||||
// if equal prefer to go down, right b/c up/left is evil first but
|
// if equal prefer to go down, right b/c up/left is evil first but
|
||||||
if (weightBoard(x)(y) == weightBoard(maxField _1)(maxField _2)){
|
if (weightBoard(x)(y) == weightBoard(maxField _1)(maxField _2)) {
|
||||||
if (x > (maxField _1) || y > (maxField _2)) maxField = (x, y)
|
if (x > (maxField _1) || y > (maxField _2)) maxField = (x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,9 +66,9 @@ class Cortex {
|
||||||
var maxDir: Direction = randomDirection(directions)
|
var maxDir: Direction = randomDirection(directions)
|
||||||
val board = state.board
|
val board = state.board
|
||||||
|
|
||||||
for (d <- directions){
|
for (d <- directions) {
|
||||||
var (x,y) = (mod (field.x+d.deltaX) (S.width), mod (field.y+d.deltaY) (S.width))
|
var (x, y) = (mod(field.x + d.deltaX)(S.width), mod(field.y + d.deltaY)(S.width))
|
||||||
var (maxX, maxY) = (mod (field.x+maxDir.deltaX) (S.width), mod (field.y+maxDir.deltaY) (S.width))
|
var (maxX, maxY) = (mod(field.x + maxDir.deltaX)(S.width), mod(field.y + maxDir.deltaY)(S.width))
|
||||||
|
|
||||||
if (weightBoard(x)(y) > weightBoard(maxX)(maxY)) maxDir = d
|
if (weightBoard(x)(y) > weightBoard(maxX)(maxY)) maxDir = d
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class Cortex {
|
||||||
maxDir
|
maxDir
|
||||||
}
|
}
|
||||||
|
|
||||||
def manhattan(x: Int, y: Int)(a: Int, b: Int): Int = math.abs(x-a) + math.abs(y-b)
|
def manhattan(x: Int, y: Int)(a: Int, b: Int): Int = math.abs(x - a) + math.abs(y - b)
|
||||||
|
|
||||||
def possibleDirections(field: Field, state: State): Seq[Direction] = {
|
def possibleDirections(field: Field, state: State): Seq[Direction] = {
|
||||||
val pd = new mutable.ListBuffer[Direction]
|
val pd = new mutable.ListBuffer[Direction]
|
||||||
|
@ -86,8 +86,8 @@ class Cortex {
|
||||||
val toCheck = checkBorder(field, state)
|
val toCheck = checkBorder(field, state)
|
||||||
|
|
||||||
for (d <- toCheck) {
|
for (d <- toCheck) {
|
||||||
if ( d == Left && board(field.x)(field.y).citizens.contains(Gate("l")) ) pd += d
|
if (d == Left && board(field.x)(field.y).citizens.contains(Gate("l"))) pd += d
|
||||||
else if ( d == Right && board(field.x)(field.y).citizens.contains(Gate("r")) ) pd += d
|
else if (d == Right && board(field.x)(field.y).citizens.contains(Gate("r"))) pd += d
|
||||||
else {
|
else {
|
||||||
val pfield = board(field.x + d.deltaX)(field.y + d.deltaY)
|
val pfield = board(field.x + d.deltaX)(field.y + d.deltaY)
|
||||||
if (!(pfield.citizens contains Wall)) {
|
if (!(pfield.citizens contains Wall)) {
|
||||||
|
@ -102,27 +102,42 @@ class Cortex {
|
||||||
def preventFallBack(weightBoard: Array[Array[Int]], state: State): Unit = {
|
def preventFallBack(weightBoard: Array[Array[Int]], state: State): Unit = {
|
||||||
val lastBofaField = Scribble.lastBofaField
|
val lastBofaField = Scribble.lastBofaField
|
||||||
|
|
||||||
if (lastBofaField != Field.empty){
|
if (lastBofaField != Field.empty) {
|
||||||
// if something changed allow fallback
|
// if something changed allow fallback
|
||||||
log(s"lastFieldWeight=${Scribble.lastFieldWeight}")
|
log(s"lastFieldWeight=${Scribble.lastFieldWeight}")
|
||||||
if (Scribble.lastFieldWeight == weightBoard(lastBofaField.x)(lastBofaField.y)){
|
if (Scribble.lastFieldWeight == weightBoard(lastBofaField.x)(lastBofaField.y)) {
|
||||||
Scribble.lastFieldWeight = weightBoard(state.bofaField.x)(state.bofaField.y)
|
Scribble.lastFieldWeight = weightBoard(state.bofaField.x)(state.bofaField.y)
|
||||||
val x: Int = weightBoard(lastBofaField.x)(lastBofaField.y)
|
val x: Int = weightBoard(lastBofaField.x)(lastBofaField.y)
|
||||||
weightBoard(lastBofaField.x)(lastBofaField.y) = (x - (0.1 * x)).intValue()
|
weightBoard(lastBofaField.x)(lastBofaField.y) = (0.5 * x).intValue()
|
||||||
} else{
|
} else {
|
||||||
Scribble.lastFieldWeight = weightBoard(state.bofaField.x)(state.bofaField.y)
|
Scribble.lastFieldWeight = weightBoard(state.bofaField.x)(state.bofaField.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def weightCodes(start: Int, drop: (Int, Int) => Int, state: State): Array[Array[Int]] = {
|
def preventLethal(weightBoard: Array[Array[Int]], state: State): Unit = {
|
||||||
|
val board = state.board
|
||||||
|
for (bug <- state.bugs) {
|
||||||
|
val dirs = possibleDirections(bug, state)
|
||||||
|
for (d <- dirs) {
|
||||||
|
var (x, y) = (bug.x + d.deltaX, bug.y + d.deltaY)
|
||||||
|
if (d == Left && board(bug.x)(bug.y).citizens.contains(Gate("l"))) x = S.width - 1
|
||||||
|
else if (d == Right && board(bug.x)(bug.y).citizens.contains(Gate("r"))) x = 0
|
||||||
|
|
||||||
|
weightBoard(x)(y) = (weightBoard(x)(y) * 0.1).intValue()
|
||||||
|
}
|
||||||
|
weightBoard(bug.x)(bug.y) = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def weightCodes(start: Int, weigh: (Int, Int, Int) => Int, state: State): Array[Array[Int]] = {
|
||||||
val board = state.board
|
val board = state.board
|
||||||
val codes = state.codes
|
val codes = state.codes
|
||||||
val weightBoard = Array.ofDim[Int](S.width, S.height)
|
val weightBoard = Array.ofDim[Int](S.width, S.height)
|
||||||
|
for (x <- 0 until S.width; y <- 0 until S.height) weightBoard(x)(y) = 10
|
||||||
|
|
||||||
log(s"Codes: ${codes.length}")
|
log(s"Codes: ${codes.length}")
|
||||||
|
|
||||||
|
|
||||||
for (code <- codes) {
|
for (code <- codes) {
|
||||||
val visited = Array.ofDim[Boolean](S.width, S.height)
|
val visited = Array.ofDim[Boolean](S.width, S.height)
|
||||||
for (x <- 0 until S.width; y <- 0 until S.height) visited(x)(y) = false
|
for (x <- 0 until S.width; y <- 0 until S.height) visited(x)(y) = false
|
||||||
|
@ -131,28 +146,30 @@ class Cortex {
|
||||||
val frontier = new mutable.ListBuffer[Field]
|
val frontier = new mutable.ListBuffer[Field]
|
||||||
|
|
||||||
frontier += code
|
frontier += code
|
||||||
|
visited(code.x)(code.y) = true
|
||||||
var weight = start
|
var weight = start
|
||||||
var dist = 0
|
var dist = 0
|
||||||
|
|
||||||
while (weight >= drop(dist, start) && !frontier.isEmpty) {
|
while (!frontier.isEmpty) {
|
||||||
coords = frontier.toList
|
coords = frontier.toList
|
||||||
frontier.clear()
|
frontier.clear()
|
||||||
|
|
||||||
for(field <- coords){
|
for (field <- coords) {
|
||||||
|
|
||||||
val dirs = possibleDirections(field, state)
|
val dirs = possibleDirections(field, state)
|
||||||
for (d <- dirs) {
|
for (d <- dirs) {
|
||||||
var (x,y) = (field.x+d.deltaX, field.y+d.deltaY)
|
var (x, y) = (field.x + d.deltaX, field.y + d.deltaY)
|
||||||
if ( d == Left && board(field.x)(field.y).citizens.contains(Gate("l")) ) x = S.width-1
|
if (d == Left && board(field.x)(field.y).citizens.contains(Gate("l"))) x = S.width - 1
|
||||||
else if ( d == Right && board(field.x)(field.y).citizens.contains(Gate("r")) ) x = 0
|
else if (d == Right && board(field.x)(field.y).citizens.contains(Gate("r"))) x = 0
|
||||||
|
|
||||||
if (!visited(x)(y)) frontier += board(x)(y)
|
if (!visited(x)(y)) frontier += board(x)(y)
|
||||||
|
visited(x)(y) = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!visited(field.x)(field.y)) weightBoard(field.x)(field.y) += weight
|
weightBoard(field.x)(field.y) += weight
|
||||||
visited(field.x)(field.y) = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
weight -= drop(dist, start)
|
weight = weigh(start, dist, weight)
|
||||||
dist += 1
|
dist += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,9 +181,9 @@ class Cortex {
|
||||||
val dirs = new mutable.ListBuffer[Direction]
|
val dirs = new mutable.ListBuffer[Direction]
|
||||||
|
|
||||||
if (field.y != 0) dirs += Up
|
if (field.y != 0) dirs += Up
|
||||||
if (field.y != (S.height-1)) dirs += Down
|
if (field.y != (S.height - 1)) dirs += Down
|
||||||
if (field.x != 0 || field.citizens.contains(Gate("l"))) dirs += Left
|
if (field.x != 0 || field.citizens.contains(Gate("l"))) dirs += Left
|
||||||
if (field.x != (S.width-1) || field.citizens.contains(Gate("r"))) dirs += Right
|
if (field.x != (S.width - 1) || field.citizens.contains(Gate("r"))) dirs += Right
|
||||||
|
|
||||||
dirs
|
dirs
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ package bot
|
||||||
object DebugUtil {
|
object DebugUtil {
|
||||||
var state: Option[State] = None // we need this to get access to the current game round
|
var state: Option[State] = None // we need this to get access to the current game round
|
||||||
val Dbg: Boolean = false
|
val Dbg: Boolean = false
|
||||||
val Log: Boolean = false
|
val Log: Boolean = true
|
||||||
val Time: Boolean = false
|
val Time: Boolean = true
|
||||||
|
|
||||||
def dbg(msg: String) = if(Dbg) Console.err.println(s"$round $msg")
|
def dbg(msg: String) = if(Dbg) Console.err.println(s"$round $msg")
|
||||||
def log(msg: String) = if(Log) Console.err.println(s"$round $msg")
|
def log(msg: String) = if(Log) Console.err.println(s"$round $msg")
|
||||||
|
|
Loading…
Reference in a new issue