Robot Rumble ALPHA
discord
try it!
boards
tutorial
docs
login
/
signup
import random import math import hashlib import struct BASE62_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" def base62_encode(data: bytes) -> str: num = int.from_bytes(data, "big") if num == 0: return BASE62_ALPHABET[0] result = [] while num > 0: num, rem = divmod(num, 62) result.append(BASE62_ALPHABET[rem]) return ''.join(reversed(result)) def base62_decode(encoded: str) -> bytes: num = 0 for char in encoded: num = num * 62 + BASE62_ALPHABET.index(char) byte_length = (num.bit_length() + 7) // 8 return num.to_bytes(byte_length, "big") def compress_floats(float_list): quantized = [int((f + 1) * 32767.5) for f in float_list] byte_data = struct.pack('>' + 'H' * len(quantized), *quantized) encoded_data = base62_encode(byte_data) return encoded_data def decompress_floats(encoded_data): byte_data = base62_decode(encoded_data) quantized = struct.unpack('>' + 'H' * (len(byte_data) // 2), byte_data) return [(q / 32767.5) - 1 for q in quantized] def fingerprint(float_list): byte_data = struct.pack('>' + 'f' * len(float_list), *float_list) hash_obj = hashlib.sha256(byte_data) fingerprint = hash_obj.hexdigest() return fingerprint def leaky_relu(x, alpha=0.01): return x if x > 0 else alpha * x def softmax(values): exp_values = [math.exp(v) for v in values] sum_exp_values = sum(exp_values) probabilities = [v / sum_exp_values for v in exp_values] return probabilities def argmax(values): max_index = 0 max_value = values[0] for i in range(1, len(values)): if values[i] > max_value: max_value = values[i] max_index = i return max_index class Linear: def __init__(self, input_size, output_size, activation): self.input_size = input_size self.output_size = output_size self.activation = activation self.weights = [[random.uniform(-1, 1) for _ in range(input_size)] for _ in range(output_size)] self.biases = [random.uniform(-1, 1) for _ in range(output_size)] def forward(self, inputs): return [ self.activation(sum(w * inp for w, inp in zip(weights, inputs)) + bias) for weights, bias in zip(self.weights, self.biases) ] def get_parameters(self): return [w for row in self.weights for w in row] + self.biases def set_parameters(self, parameters): for i in range(self.output_size): for j in range(self.input_size): self.weights[i][j] = parameters[i * self.input_size + j] self.biases = parameters[self.input_size * self.output_size:] class NeuralNetwork: def __init__(self, input_size, hidden_size, output_size): self.input_layer = Linear(input_size, hidden_size, activation=leaky_relu) self.hidden_layer = Linear(hidden_size, hidden_size, activation=leaky_relu) self.output_layer = Linear(hidden_size, output_size, activation=leaky_relu) def forward(self, inputs): return self.output_layer.forward(self.hidden_layer.forward(self.input_layer.forward(inputs))) def get_parameters(self): return self.input_layer.get_parameters() + self.hidden_layer.get_parameters() + self.output_layer.get_parameters() def set_parameters(self, parameters): input_length = len(self.input_layer.get_parameters()) hidden_length = len(self.hidden_layer.get_parameters()) self.input_layer.set_parameters(parameters[:input_length]) self.hidden_layer.set_parameters(parameters[input_length:input_length + hidden_length]) self.output_layer.set_parameters(parameters[input_length + hidden_length:]) shared_state = [0.0, 0.0, 0.0, 0.0, 0.0] network = NeuralNetwork(input_size=12, hidden_size=24, output_size=12) network.set_parameters(decompress_floats( "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" )) def health_by_coords(state, coord): obj = state.obj_by_coords(coord) if obj and obj.team is not None: return obj.health / 5 if obj.team == state.our_team else -obj.health / 5 return 0 def robot(state, unit): global shared_state x = (float(unit.coords.x) - 10) / 10 y = (float(unit.coords.y) - 10) / 10 r = math.sqrt(x * x + y * y) inputs = [x, y, r] + [ health_by_coords(state, coord) for coord in unit.coords.coords_around() ] + shared_state output = network.forward(inputs) action_value, direction_value, decay_coeff, shared_updates = output[:2], output[2:6], output[7], output[7:] total_units = len(state.ids_by_team(state.our_team)) + len(state.ids_by_team(state.other_team)) memory_decay = (1 + math.tanh(decay_coeff)) * (1 + math.tanh(total_units - 20)) / 4 shared_state[:] = [ math.tanh((1 - memory_decay) * s + memory_decay * u) for s, u in zip(shared_state, shared_updates) ] action_type = [ActionType.Move, ActionType.Attack][argmax(softmax(action_value))] direction = [ Direction.North, Direction.South, Direction.East, Direction.West ][argmax(softmax(direction_value))] return Action.move(direction) if action_type == ActionType.Move else Action.attack(direction)
Made with <3 by Anton and Noa
github org