new map, faster genetic algorithm
This commit is contained in:
parent
8e7e279c4b
commit
dfac987643
@ -27,7 +27,7 @@ def sum_distance(speciment):
|
|||||||
|
|
||||||
# tournament selection
|
# tournament selection
|
||||||
# this function randomly puts speciments to groups, from each group one best speciment is taken for reproduction
|
# this function randomly puts speciments to groups, from each group one best speciment is taken for reproduction
|
||||||
def selection(pop, scores, k=3):
|
def selection(pop, scores, k=10):
|
||||||
# first random selection
|
# first random selection
|
||||||
selection_ix = randint(len(pop))
|
selection_ix = randint(len(pop))
|
||||||
for ix in randint(0, len(pop), k- 1):
|
for ix in randint(0, len(pop), k- 1):
|
||||||
@ -66,7 +66,7 @@ def crossover(p1, p2, r_cross):
|
|||||||
# this function checks whether genes mutated
|
# this function checks whether genes mutated
|
||||||
# if gene is mutated then it is swapped with randomly chosen gene from the same speciment
|
# if gene is mutated then it is swapped with randomly chosen gene from the same speciment
|
||||||
def mutation(speciment, r_mut):
|
def mutation(speciment, r_mut):
|
||||||
for i in range(len(speciment)-1):
|
for i in range(len(speciment)):
|
||||||
# check for a mutation
|
# check for a mutation
|
||||||
if rand() < r_mut:
|
if rand() < r_mut:
|
||||||
# flip the bit
|
# flip the bit
|
||||||
@ -126,12 +126,12 @@ if __name__ == "__main__":
|
|||||||
# crossover rate
|
# crossover rate
|
||||||
r_cross = 0.9
|
r_cross = 0.9
|
||||||
# mutation rate
|
# mutation rate
|
||||||
r_mut = 0.05
|
r_mut = 0.15
|
||||||
|
|
||||||
# create new minefield instance
|
# create new minefield instance
|
||||||
import os
|
import os
|
||||||
from minefield import Minefield
|
from minefield import Minefield
|
||||||
minefield = Minefield(os.path.join("..", "..", "..", "resources", "minefields", "fourthmap.json"))
|
minefield = Minefield(os.path.join("..", "..", "..", "resources", "minefields", "fifthmap.json"))
|
||||||
|
|
||||||
# perform the genetic algorithm search
|
# perform the genetic algorithm search
|
||||||
best, score = genetic_algorithm(minefield, helpers.get_score, n_iter, n_pop, r_cross, r_mut)
|
best, score = genetic_algorithm(minefield, helpers.get_score, n_iter, n_pop, r_cross, r_mut)
|
||||||
|
@ -4,35 +4,134 @@ import project_constants as const
|
|||||||
from project_constants import Direction
|
from project_constants import Direction
|
||||||
from algorithms.search.a_star import State, graphsearch
|
from algorithms.search.a_star import State, graphsearch
|
||||||
from objects.mine_models.chained_mine import ChainedMine
|
from objects.mine_models.chained_mine import ChainedMine
|
||||||
|
from objects.mine_models.time_mine import TimeMine
|
||||||
|
|
||||||
|
|
||||||
def get_score(minefield, speciment):
|
def possible_states(row, column):
|
||||||
initial_state = State(row=0, column=0, direction=Direction.RIGHT)
|
possible_states = []
|
||||||
score = 0
|
|
||||||
|
|
||||||
for el_index in range(len(speciment) - 1):
|
if Minefield.is_valid_move(row + 1, column):
|
||||||
action_sequence, initial_state, cost = \
|
possible_states.append(State(row + 1, column, Direction.UP))
|
||||||
graphsearch(initial_state,
|
|
||||||
|
if Minefield.is_valid_move(row - 1, column):
|
||||||
|
possible_states.append(State(row + 1, column, Direction.DOWN))
|
||||||
|
|
||||||
|
if Minefield.is_valid_move(row, column + 1):
|
||||||
|
possible_states.append(State(row, column + 1, Direction.LEFT))
|
||||||
|
|
||||||
|
if Minefield.is_valid_move(row, column - 1):
|
||||||
|
possible_states.append(State(row, column - 1, Direction.RIGHT))
|
||||||
|
|
||||||
|
return possible_states
|
||||||
|
|
||||||
|
|
||||||
|
def create_scores_table(minefield):
|
||||||
|
mines = get_mines_coords(minefield)
|
||||||
|
dict_table = {
|
||||||
|
mine1: {
|
||||||
|
mine2: {
|
||||||
|
direction: 0
|
||||||
|
|
||||||
|
for direction in Direction}
|
||||||
|
for mine2 in mines}
|
||||||
|
for mine1 in mines}
|
||||||
|
|
||||||
|
dict_table[(0, 0)] = {mine: {Direction.RIGHT: 0} for mine in mines}
|
||||||
|
|
||||||
|
for mine in mines:
|
||||||
|
_, end_state, cost = \
|
||||||
|
graphsearch(State(0, 0, Direction.RIGHT),
|
||||||
minefield,
|
minefield,
|
||||||
target_type="mine",
|
target_type="mine",
|
||||||
tox=speciment[el_index][0],
|
tox=mine[0],
|
||||||
toy=speciment[el_index][1],
|
toy=mine[1],
|
||||||
with_data=True)
|
with_data=True)
|
||||||
|
|
||||||
mine = minefield.matrix[speciment[el_index][0]][speciment[el_index][1]].mine
|
dict_table[(0, 0)][mine][Direction.RIGHT] = (end_state, cost)
|
||||||
|
|
||||||
if isinstance(mine, ChainedMine) and mine.predecessor is not None and mine.predecessor.active:
|
for mine1 in mines:
|
||||||
cost += 10000
|
for mine2 in mines:
|
||||||
|
for initial_state in possible_states(mine1[0], mine1[1]):
|
||||||
|
_, end_state, cost = \
|
||||||
|
graphsearch(initial_state,
|
||||||
|
minefield,
|
||||||
|
target_type="mine",
|
||||||
|
tox=mine2[0],
|
||||||
|
toy=mine2[1],
|
||||||
|
with_data=True)
|
||||||
|
|
||||||
mine.active = False
|
dict_table[mine1][mine2][initial_state.direction] = (end_state, cost)
|
||||||
|
|
||||||
for _ in range(cost):
|
return dict_table
|
||||||
minefield.next_turn()
|
|
||||||
|
|
||||||
score += cost
|
|
||||||
|
|
||||||
score += 10000 * minefield.explosions
|
def get_score(minefield, speciment, table=None):
|
||||||
return score
|
score = 0
|
||||||
|
initial_state = State(0, 0, Direction.RIGHT)
|
||||||
|
|
||||||
|
if table is not None:
|
||||||
|
for el_index in range(len(speciment) - 1):
|
||||||
|
|
||||||
|
if table[(initial_state.row, initial_state.column)] \
|
||||||
|
[(speciment[el_index][0], speciment[el_index][1])] \
|
||||||
|
[initial_state.direction]:
|
||||||
|
|
||||||
|
end_state, cost = table[(initial_state.row, initial_state.column)] \
|
||||||
|
[(speciment[el_index][0], speciment[el_index][1])] \
|
||||||
|
[initial_state.direction]
|
||||||
|
|
||||||
|
initial_state = State(speciment[el_index][0], speciment[el_index][1], end_state.direction)
|
||||||
|
|
||||||
|
else:
|
||||||
|
action_sequence, _, cost = \
|
||||||
|
graphsearch(initial_state,
|
||||||
|
minefield,
|
||||||
|
target_type="mine",
|
||||||
|
tox=speciment[el_index][0],
|
||||||
|
toy=speciment[el_index][1],
|
||||||
|
with_data=True)
|
||||||
|
|
||||||
|
mine = minefield.matrix[speciment[el_index][0]][speciment[el_index][1]].mine
|
||||||
|
|
||||||
|
if isinstance(mine, ChainedMine) and mine.predecessor is not None and mine.predecessor.active:
|
||||||
|
cost += 200
|
||||||
|
|
||||||
|
mine.active = False
|
||||||
|
|
||||||
|
for _ in range(cost):
|
||||||
|
minefield.next_turn()
|
||||||
|
|
||||||
|
score += cost
|
||||||
|
|
||||||
|
score += 200 * minefield.explosions
|
||||||
|
|
||||||
|
return score
|
||||||
|
|
||||||
|
# IF THERE IS NO TABLE
|
||||||
|
else:
|
||||||
|
for el_index in range(len(speciment) - 1):
|
||||||
|
action_sequence, initial_state, cost = \
|
||||||
|
graphsearch(initial_state,
|
||||||
|
minefield,
|
||||||
|
target_type="mine",
|
||||||
|
tox=speciment[el_index][0],
|
||||||
|
toy=speciment[el_index][1],
|
||||||
|
with_data=True)
|
||||||
|
|
||||||
|
mine = minefield.matrix[speciment[el_index][0]][speciment[el_index][1]].mine
|
||||||
|
|
||||||
|
if isinstance(mine, ChainedMine) and mine.predecessor is not None and mine.predecessor.active:
|
||||||
|
cost += 200
|
||||||
|
|
||||||
|
mine.active = False
|
||||||
|
|
||||||
|
for _ in range(cost):
|
||||||
|
minefield.next_turn()
|
||||||
|
|
||||||
|
score += cost
|
||||||
|
|
||||||
|
score += 200 * minefield.explosions
|
||||||
|
return score
|
||||||
|
|
||||||
|
|
||||||
def get_mines_coords(minefield: Minefield):
|
def get_mines_coords(minefield: Minefield):
|
||||||
@ -43,6 +142,6 @@ def get_mines_coords(minefield: Minefield):
|
|||||||
mine = minefield.matrix[row][column].mine
|
mine = minefield.matrix[row][column].mine
|
||||||
|
|
||||||
if mine is not None:
|
if mine is not None:
|
||||||
mines.append([row, column])
|
mines.append((row, column))
|
||||||
|
|
||||||
return mines
|
return mines
|
169
algorithms/learn/genetic_algorithm/new_ga.py
Normal file
169
algorithms/learn/genetic_algorithm/new_ga.py
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
import numpy as np, random, operator, pandas as pd
|
||||||
|
from algorithms.learn.genetic_algorithm import helpers
|
||||||
|
|
||||||
|
import os
|
||||||
|
from minefield import Minefield
|
||||||
|
gl_minefield = None
|
||||||
|
scores_table = None
|
||||||
|
|
||||||
|
|
||||||
|
class Fitness:
|
||||||
|
def __init__(self, route):
|
||||||
|
self.route = route
|
||||||
|
self.distance = 0
|
||||||
|
self.fitness = 0.0
|
||||||
|
|
||||||
|
def routeDistance(self):
|
||||||
|
if self.distance == 0:
|
||||||
|
self.distance = helpers.get_score(gl_minefield, self.route, scores_table)
|
||||||
|
|
||||||
|
return self.distance
|
||||||
|
|
||||||
|
def routeFitness(self):
|
||||||
|
if self.fitness == 0:
|
||||||
|
self.fitness = 1000 / float(self.routeDistance())
|
||||||
|
return self.fitness
|
||||||
|
|
||||||
|
|
||||||
|
def createRoute(cityList):
|
||||||
|
route = random.sample(cityList, len(cityList))
|
||||||
|
return route
|
||||||
|
|
||||||
|
|
||||||
|
def initialPopulation(popSize, cityList):
|
||||||
|
population = []
|
||||||
|
|
||||||
|
for i in range(0, popSize):
|
||||||
|
population.append(createRoute(cityList))
|
||||||
|
return population
|
||||||
|
|
||||||
|
|
||||||
|
def rankRoutes(population):
|
||||||
|
fitnessResults = {}
|
||||||
|
for i in range(0, len(population)):
|
||||||
|
fitnessResults[i] = Fitness(population[i]).routeFitness()
|
||||||
|
return sorted(fitnessResults.items(), key=operator.itemgetter(1), reverse=True)
|
||||||
|
|
||||||
|
|
||||||
|
def selection(popRanked, eliteSize):
|
||||||
|
selectionResults = []
|
||||||
|
df = pd.DataFrame(np.array(popRanked), columns=["Index", "Fitness"])
|
||||||
|
df['cum_sum'] = df.Fitness.cumsum()
|
||||||
|
df['cum_perc'] = 100 * df.cum_sum / df.Fitness.sum()
|
||||||
|
|
||||||
|
for i in range(0, eliteSize):
|
||||||
|
selectionResults.append(popRanked[i][0])
|
||||||
|
for i in range(0, len(popRanked) - eliteSize):
|
||||||
|
pick = 100 * random.random()
|
||||||
|
for i in range(0, len(popRanked)):
|
||||||
|
if pick <= df.iat[i, 3]:
|
||||||
|
selectionResults.append(popRanked[i][0])
|
||||||
|
break
|
||||||
|
return selectionResults
|
||||||
|
|
||||||
|
def matingPool(population, selectionResults):
|
||||||
|
matingpool = []
|
||||||
|
for i in range(0, len(selectionResults)):
|
||||||
|
index = selectionResults[i]
|
||||||
|
matingpool.append(population[index])
|
||||||
|
return matingpool
|
||||||
|
|
||||||
|
|
||||||
|
def breed(parent1, parent2):
|
||||||
|
child = []
|
||||||
|
childP1 = []
|
||||||
|
childP2 = []
|
||||||
|
|
||||||
|
geneA = int(random.random() * len(parent1))
|
||||||
|
geneB = int(random.random() * len(parent1))
|
||||||
|
|
||||||
|
startGene = min(geneA, geneB)
|
||||||
|
endGene = max(geneA, geneB)
|
||||||
|
|
||||||
|
for i in range(startGene, endGene):
|
||||||
|
childP1.append(parent1[i])
|
||||||
|
|
||||||
|
childP2 = [item for item in parent2 if item not in childP1]
|
||||||
|
|
||||||
|
child = childP1 + childP2
|
||||||
|
return child
|
||||||
|
|
||||||
|
|
||||||
|
def breedPopulation(matingpool, eliteSize):
|
||||||
|
children = []
|
||||||
|
length = len(matingpool) - eliteSize
|
||||||
|
pool = random.sample(matingpool, len(matingpool))
|
||||||
|
|
||||||
|
for i in range(0, eliteSize):
|
||||||
|
children.append(matingpool[i])
|
||||||
|
|
||||||
|
for i in range(0, length):
|
||||||
|
child = breed(pool[i], pool[len(matingpool) - i - 1])
|
||||||
|
children.append(child)
|
||||||
|
return children
|
||||||
|
|
||||||
|
|
||||||
|
def mutate(individual, mutationRate):
|
||||||
|
for swapped in range(len(individual)):
|
||||||
|
if (random.random() < mutationRate):
|
||||||
|
swapWith = int(random.random() * len(individual))
|
||||||
|
|
||||||
|
city1 = individual[swapped]
|
||||||
|
city2 = individual[swapWith]
|
||||||
|
|
||||||
|
individual[swapped] = city2
|
||||||
|
individual[swapWith] = city1
|
||||||
|
return individual
|
||||||
|
|
||||||
|
|
||||||
|
def mutatePopulation(population, mutationRate):
|
||||||
|
mutatedPop = []
|
||||||
|
|
||||||
|
for ind in range(0, len(population)):
|
||||||
|
mutatedInd = mutate(population[ind], mutationRate)
|
||||||
|
mutatedPop.append(mutatedInd)
|
||||||
|
return mutatedPop
|
||||||
|
|
||||||
|
|
||||||
|
def nextGeneration(scores, currentGen, eliteSize, mutationRate):
|
||||||
|
selectionResults = selection(scores, eliteSize)
|
||||||
|
matingpool = matingPool(currentGen, selectionResults)
|
||||||
|
children = breedPopulation(matingpool, eliteSize)
|
||||||
|
nextGeneration = mutatePopulation(children, mutationRate)
|
||||||
|
return nextGeneration
|
||||||
|
|
||||||
|
|
||||||
|
def genetic_algorithm(minefield, population, popSize, eliteSize, mutationRate, generations):
|
||||||
|
global gl_minefield, scores_table
|
||||||
|
gl_minefield = minefield
|
||||||
|
|
||||||
|
scores_table = helpers.create_scores_table(gl_minefield)
|
||||||
|
|
||||||
|
pop = initialPopulation(popSize, population)
|
||||||
|
scores = rankRoutes(pop)
|
||||||
|
|
||||||
|
print("Initial score: " + str(1000 / scores[0][1]))
|
||||||
|
|
||||||
|
for i in range(0, generations):
|
||||||
|
pop = nextGeneration(scores, pop, eliteSize, mutationRate)
|
||||||
|
scores = rankRoutes(pop)
|
||||||
|
print(f"Generation {i} best score: {str(1000 / scores[0][1])}")
|
||||||
|
bestRouteIndex = scores[0][0]
|
||||||
|
bestRoute = pop[bestRouteIndex]
|
||||||
|
print(bestRoute)
|
||||||
|
|
||||||
|
print("Final score: " + str(1000 / scores[0][1]))
|
||||||
|
bestRouteIndex = scores[0][0]
|
||||||
|
bestRoute = pop[bestRouteIndex]
|
||||||
|
return bestRoute
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
gl_minefield = Minefield(os.path.join("..", "..", "..", "resources", "minefields", "fifthmap.json"))
|
||||||
|
|
||||||
|
genetic_algorithm(minefield=gl_minefield,
|
||||||
|
population=helpers.get_mines_coords(gl_minefield),
|
||||||
|
popSize=100,
|
||||||
|
eliteSize=20,
|
||||||
|
mutationRate=0.01,
|
||||||
|
generations=100)
|
@ -58,7 +58,7 @@ def blit_graphics(minefield):
|
|||||||
pass # darken_tile(tile.position)
|
pass # darken_tile(tile.position)
|
||||||
|
|
||||||
# draw a mine on top if there is one
|
# draw a mine on top if there is one
|
||||||
if tile.mine is not None and tile.mine.active:
|
if tile.mine is not None:
|
||||||
if isinstance(tile.mine, StandardMine):
|
if isinstance(tile.mine, StandardMine):
|
||||||
const.SCREEN.blit(mine_asset_options["MINE"], tile_screen_coords)
|
const.SCREEN.blit(mine_asset_options["MINE"], tile_screen_coords)
|
||||||
|
|
||||||
|
13
game.py
13
game.py
@ -5,7 +5,7 @@ import project_constants as const
|
|||||||
from assets.display_assets import blit_graphics
|
from assets.display_assets import blit_graphics
|
||||||
from algorithms.search import a_star
|
from algorithms.search import a_star
|
||||||
|
|
||||||
from algorithms.learn.genetic_algorithm import genetic_algorithm, helpers
|
from algorithms.learn.genetic_algorithm import new_ga, helpers
|
||||||
|
|
||||||
from minefield import Minefield
|
from minefield import Minefield
|
||||||
|
|
||||||
@ -141,11 +141,14 @@ class Game:
|
|||||||
def run_genetics(self):
|
def run_genetics(self):
|
||||||
genetics_minefield = Minefield(const.MAP_RANDOM_10x10)
|
genetics_minefield = Minefield(const.MAP_RANDOM_10x10)
|
||||||
|
|
||||||
sequence, score = \
|
sequence = \
|
||||||
genetic_algorithm.genetic_algorithm(genetics_minefield, helpers.get_score, 10, 100, 0.9, 0.05)
|
new_ga.genetic_algorithm(minefield=genetics_minefield,
|
||||||
|
population=helpers.get_mines_coords(self.minefield),
|
||||||
|
popSize=100,
|
||||||
|
eliteSize=20,
|
||||||
|
mutationRate=0.01,
|
||||||
|
generations=15)
|
||||||
|
|
||||||
print('Done!')
|
|
||||||
print('f(%s) = %f' % (sequence, score))
|
|
||||||
self.genetic_sequence = sequence
|
self.genetic_sequence = sequence
|
||||||
|
|
||||||
def set_next_genetic_target(self):
|
def set_next_genetic_target(self):
|
||||||
|
@ -31,8 +31,11 @@ class Agent:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def defuse_a_mine(mine):
|
def defuse_a_mine(mine):
|
||||||
is_success = popup.disarming_popup(mine)
|
if mine.active:
|
||||||
return is_success
|
is_success = popup.disarming_popup(mine)
|
||||||
|
return is_success
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
def update_and_draw(self, window, delta_time, minefield):
|
def update_and_draw(self, window, delta_time, minefield):
|
||||||
self.update(delta_time, minefield)
|
self.update(delta_time, minefield)
|
||||||
|
@ -11,6 +11,7 @@ class TimeMine(Mine):
|
|||||||
|
|
||||||
def disarm(self, wire):
|
def disarm(self, wire):
|
||||||
if self.active:
|
if self.active:
|
||||||
|
self.starting_time = 0
|
||||||
return super().disarm(wire)
|
return super().disarm(wire)
|
||||||
else:
|
else:
|
||||||
# mine has already exploded, no need to return failure
|
# mine has already exploded, no need to return failure
|
||||||
|
@ -6,7 +6,8 @@ from project_constants import Terrain
|
|||||||
# It is used in Tile.cost (giving the value to the tile)
|
# It is used in Tile.cost (giving the value to the tile)
|
||||||
|
|
||||||
def assume_cost(terrain_type, mine):
|
def assume_cost(terrain_type, mine):
|
||||||
if mine is not None and mine.active:
|
# to allow walking through inactive mines -> and mine.active
|
||||||
|
if mine is not None:
|
||||||
return Terrain.MINE
|
return Terrain.MINE
|
||||||
if terrain_type == "CONCRETE":
|
if terrain_type == "CONCRETE":
|
||||||
return Terrain.CONCRETE
|
return Terrain.CONCRETE
|
||||||
|
@ -162,6 +162,6 @@ HIGHLIGHT.set_alpha(100)
|
|||||||
# ==== MAPS ==== #
|
# ==== MAPS ==== #
|
||||||
# ============== #
|
# ============== #
|
||||||
|
|
||||||
MAP_RANDOM_10x10 = os.path.join("resources", "minefields", "fourthmap.json")
|
MAP_RANDOM_10x10 = os.path.join("resources", "minefields", "fifthmap.json")
|
||||||
|
|
||||||
|
|
||||||
|
479
resources/minefields/fifthmap.json
Normal file
479
resources/minefields/fifthmap.json
Normal file
@ -0,0 +1,479 @@
|
|||||||
|
{
|
||||||
|
"0,0": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"0,1": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"0,2": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"0,3": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "time",
|
||||||
|
"timer": 77
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0,4": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "chained",
|
||||||
|
"predecessor": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0,5": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"0,6": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"0,7": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"0,8": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "standard"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0,9": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "time",
|
||||||
|
"timer": 120
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1,0": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"1,1": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "time",
|
||||||
|
"timer": 23
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1,2": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"1,3": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "chained",
|
||||||
|
"predecessor": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1,4": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"1,5": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"1,6": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"1,7": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"1,8": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"1,9": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"2,0": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"2,1": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "standard"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"2,2": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"2,3": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "chained",
|
||||||
|
"predecessor": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"2,4": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"2,5": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "time",
|
||||||
|
"timer": 68
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"2,6": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"2,7": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"2,8": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "time",
|
||||||
|
"timer": 120
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"2,9": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"3,0": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"3,1": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "time",
|
||||||
|
"timer": 30
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"3,2": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"3,3": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "time",
|
||||||
|
"timer": 99
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"3,4": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"3,5": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"3,6": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "chained",
|
||||||
|
"predecessor": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"3,7": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"3,8": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"3,9": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"4,0": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"4,1": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"4,2": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "time",
|
||||||
|
"timer": 24
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"4,3": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"4,4": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"4,5": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"4,6": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"4,7": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "chained",
|
||||||
|
"predecessor": "7,0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"4,8": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"4,9": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"5,0": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"5,1": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "chained",
|
||||||
|
"predecessor": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"5,2": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"5,3": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"5,4": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "chained",
|
||||||
|
"predecessor": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"5,5": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"5,6": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"5,7": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"5,8": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"5,9": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"6,0": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"6,1": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"6,2": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"6,3": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"6,4": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"6,5": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "standard"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"6,6": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"6,7": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"6,8": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"6,9": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "standard"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"7,0": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "chained",
|
||||||
|
"predecessor": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"7,1": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"7,2": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"7,3": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"7,4": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"7,5": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "time",
|
||||||
|
"timer": 101
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"7,6": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "time",
|
||||||
|
"timer": 140
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"7,7": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"7,8": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"7,9": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"8,0": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"8,1": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "time",
|
||||||
|
"timer": 60
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"8,2": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"8,3": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "standard"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"8,4": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"8,5": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"8,6": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"8,7": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"8,8": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "chained",
|
||||||
|
"predecessor": "3,6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"8,9": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"9,0": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"9,1": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"9,2": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"9,3": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"9,4": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"9,5": {
|
||||||
|
"terrain": "GRASS",
|
||||||
|
"mine": {
|
||||||
|
"mine_type": "chained",
|
||||||
|
"predecessor": "0,4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"9,6": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"9,7": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"9,8": {
|
||||||
|
"terrain": "MUD",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"9,9": {
|
||||||
|
"terrain": "CONCRETE",
|
||||||
|
"mine": null
|
||||||
|
},
|
||||||
|
"agents_initial_state": {
|
||||||
|
"direction": 1,
|
||||||
|
"position": "0,0"
|
||||||
|
}
|
||||||
|
}
|
@ -48,7 +48,7 @@
|
|||||||
"terrain": "MUD",
|
"terrain": "MUD",
|
||||||
"mine": {
|
"mine": {
|
||||||
"mine_type": "time",
|
"mine_type": "time",
|
||||||
"timer": 320
|
"timer": 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"1,0": {
|
"1,0": {
|
||||||
@ -154,7 +154,7 @@
|
|||||||
"terrain": "GRASS",
|
"terrain": "GRASS",
|
||||||
"mine": {
|
"mine": {
|
||||||
"mine_type": "time",
|
"mine_type": "time",
|
||||||
"timer": 40
|
"timer": 30
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"3,2": {
|
"3,2": {
|
||||||
@ -363,7 +363,7 @@
|
|||||||
"terrain": "MUD",
|
"terrain": "MUD",
|
||||||
"mine": {
|
"mine": {
|
||||||
"mine_type": "time",
|
"mine_type": "time",
|
||||||
"timer": 240
|
"timer": 140
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"7,7": {
|
"7,7": {
|
||||||
@ -386,7 +386,7 @@
|
|||||||
"terrain": "MUD",
|
"terrain": "MUD",
|
||||||
"mine": {
|
"mine": {
|
||||||
"mine_type": "time",
|
"mine_type": "time",
|
||||||
"timer": 150
|
"timer": 60
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"8,2": {
|
"8,2": {
|
||||||
|
Loading…
Reference in New Issue
Block a user