Created
December 25, 2022 15:22
-
-
Save kmbenjel/268dba3beb7202a23830cf8e3cb7be64 to your computer and use it in GitHub Desktop.
Just to get ideas, it is not much efficient for the moment, don't try it on CodinGame IDE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
STDOUT.sync = true # DO NOT REMOVE | |
$opp_units_initial = [] | |
# Find the farthest point in the field | |
def farthest(w, h, x, y) | |
far_x = x > w/2 ? 0 : w | |
far_y = y > h/2 ? 0 : h | |
{ x: far_x, y: far_y } | |
end | |
# Collect my tiles neighboring the opponent tiles | |
def opp_is_close(opp_tiles, my_tiles) | |
close_tiles = [] | |
opp_tiles.each do |opp_tile| | |
my_tiles.each do |my_tile| | |
if (my_tile[:x] - opp_tile[:x]).abs + (my_tile[:y] - opp_tile[:y]).abs == 1 | |
close_tiles << my_tile | |
end | |
end | |
end | |
return close_tiles | |
end | |
# Collect neighbor tiles of a tile | |
def neighbor(tile, tiles) | |
neighbors = [] | |
x, y = tile[:x], tile[:y] | |
tiles.each do |t| | |
if (x == t[:x] && (y - t[:y] == 1 || t[:y] - y == 1)) || (y == t[:y] && (x - t[:x] == 1 || t[:x] - x == 1)) | |
neighbors << t | |
end | |
end | |
neighbors | |
end | |
def opp_not_far(opp_tiles, my_tiles) | |
close_tiles = [] | |
opp_tiles.each do |opp_tile| | |
my_tiles.each do |my_tile| | |
if (my_tile[:x] - opp_tile[:x]).abs + (my_tile[:y] - opp_tile[:y]).abs <= 2 | |
close_tiles << my_tile | |
end | |
end | |
end | |
return close_tiles | |
end | |
# Check if I have scrap in the current tile and the neighboring tiles | |
def scrap_around(tiles, tile) | |
total_scrap_amount = 0 | |
tiles.each do |t| | |
if ((t[:x] == tile[:x] && t[:y] == tile[:y] + 1) || | |
(t[:x] == tile[:x] && t[:y] == tile[:y] - 1) || | |
(t[:y] == tile[:y] && t[:x] == tile[:x] + 1) || | |
(t[:y] == tile[:y] && t[:x] == tile[:x] - 1) || | |
(t[:x] == tile[:x] && t[:y] == tile[:y])) | |
total_scrap_amount += t[:scrap_amount] | |
end | |
end | |
return total_scrap_amount >= 3 | |
end | |
# Check if x is in the second column | |
def in_second_column(height, width, x) | |
x == 1 || x == width - 2 ? true : false | |
end | |
# Set targets for all my units | |
def set_target(my_units, width, height) | |
# if opp_is_close.empty? | |
# my_units.each do |my_unit| | |
# min_dist = nil | |
# opp_unit = nil | |
# opp_units.each do |opp_unit_pos| | |
# distance = Math.sqrt((my_unit[:x] - opp_unit_pos[:x])**2 + (my_unit[:y] - opp_unit_pos[:y])**2) | |
# if min_dist.nil? || distance < min_dist | |
# min_dist = distance | |
# opp_unit = opp_unit_pos | |
# end | |
# end | |
# my_unit[:tx], my_unit[:ty] = opp_unit[:x], opp_unit[:y] | |
# end | |
half = my_units.length / 2 | |
top_half = my_units[0..half - 1] | |
bottom_half = my_units[half..-1] | |
if my_units.first[:x] > width/2 | |
top_half.each { |unit| unit[:tx], unit[:ty] = 2, 0 } | |
bottom_half.each { |unit| unit[:tx], unit[:ty] = 2, height - 1 } | |
else | |
top_half.each { |unit| unit[:tx], unit[:ty] = width - 3, 0 } | |
bottom_half.each { |unit| unit[:tx], unit[:ty] = width - 3, height - 1 } | |
end | |
end | |
ME = 1 | |
OPP = 0 | |
NONE = -1 | |
width, height = gets.split.map &:to_i | |
role_glob = -1 | |
# game loop | |
loop { | |
role_glob += 1 | |
tiles = [] | |
my_units = [] | |
opp_units = [] | |
my_recyclers = [] | |
opp_recyclers = [] | |
opp_tiles = [] | |
my_tiles = [] | |
neutral_tiles = [] | |
my_matter, opp_matter = gets.split.map &:to_i | |
height.times { |y| | |
width.times { |x| | |
# owner: 1 = me, 0 = foe, -1 = neutral | |
scrap_amount, owner, units, recycler, can_build, can_spawn, in_range_of_recycler = gets.split.map &:to_i | |
tile = { | |
scrap_amount: scrap_amount, | |
owner: owner, | |
units: units, | |
recycler: recycler, | |
can_build: can_build==1, | |
can_spawn: can_spawn==1, | |
in_range_of_recycler: in_range_of_recycler==1, | |
x: x, | |
y: y | |
} | |
tiles.append(tile) | |
if tile[:owner] == ME | |
my_tiles.append(tile) | |
if tile[:units] > 0 | |
my_units.append(tile) | |
tile[:reachable] = true | |
elsif tile[:recycler] == 1 | |
my_recyclers.append(tile) | |
end | |
elsif tile[:owner] == OPP | |
opp_tiles.append(tile) | |
if tile[:units] > 0 | |
opp_units.append(tile) | |
tile[:reachable] = true | |
elsif tile[:recycler] == 1 | |
opp_recyclers.append(tile) | |
end | |
else | |
neutral_tiles.append(tile) | |
tile[:reachable] = true | |
end | |
} | |
# PARSING DONE | |
} | |
if role_glob == 0 | |
$opp_units_initial = opp_units | |
end | |
actions = [] | |
my_robots = my_units.map { |t| t[:units] }.sum | |
opp_robots = opp_units.map { |t| t[:units] }.sum | |
first_opp = opp_tiles.first | |
opp_is_close = opp_is_close(opp_tiles, my_tiles) | |
opp_not_far = opp_not_far(opp_tiles, my_tiles) | |
role = 0 | |
builds = 0 | |
matter_for_units = my_matter / 10 | |
my_tiles.each { |tile| | |
spawned = false | |
x = tile[:x] | |
y = tile[:y] | |
units = tile[:units] > 0 | |
no_units = tile[:units] == 0 | |
tile_near_opp = opp_is_close.any?(tile) | |
in_second_column = in_second_column(height, width, x) | |
scrap_around = scrap_around(tiles, tile) | |
build_here = scrap_around && tile_near_opp && role_glob % 6 == 1 | |
my_empty_tiles = my_tiles.select { |t| t[:units] == 0 } | |
empty_count = my_empty_tiles.count | |
if tile[:can_spawn] | |
amount = 0 | |
if matter_for_units > 1 && ((role % 5 != 0) || my_units.count <= 4) | |
if no_units | |
amount = 1 | |
elsif builds > 0 || my_robots < opp_robots | |
amount = matter_for_units | |
end | |
end | |
if amount > 0 | |
actions<<"SPAWN #{amount} #{tile[:x]} #{tile[:y]}" | |
matter_for_units -= amount | |
spawned = true | |
end | |
end | |
if tile[:can_build] && !spawned && build_here | |
if matter_for_units > 0 | |
should_build = true | |
else | |
should_build = false | |
end | |
if should_build | |
actions<<"BUILD #{tile[:x]} #{tile[:y]}" | |
builds += 1 | |
tile[:built] = 1 | |
my_matter -= 10 | |
end | |
end | |
set_target(my_tiles, width, height) | |
target = { x: tile[:tx], y: tile[:ty] } | |
if units && target && !spawned && !tile[:built] | |
neighbors = neighbor(tile, tiles) | |
amount = 1 #[tile[:units], 2].min | |
if amount > 0 && target | |
if [x, y] == [tile[:tx], tile[:ty]] | |
empty = neighbors.select { |t| t[:units] == 0 }.shuffle.first.to_a | |
neighbor = neighbors.select { |t| t[:reachable] }.shuffle.first.to_a | |
any_empty = empty.any? | |
any_neighbor = neighbor.any? | |
if any_empty | |
target[:x], target[:y] = empty[:x], empty[:y] | |
elsif any_neighbor | |
target[:x], target[:y] = units[:x], units[:y] | |
end | |
end | |
#if role_glob % 2 == 0 && role % 5 in [2, 3] | |
#target[:x], target[:y] = x + [1, -1].shuffle.first, y + [1, -1].shuffle.first | |
#end | |
actions<<"MOVE #{amount} #{tile[:x]} #{tile[:y]} #{target[:x]} #{target[:y]}" | |
end | |
end | |
role += 1 | |
} | |
# To debug: STDERR.puts "Debug messages..." | |
puts actions.size > 0 ? actions*";" : "WAIT" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment