new map, faster genetic algorithm
This commit is contained in:
parent
8e7e279c4b
commit
dfac987643
@ -27,7 +27,7 @@ def sum_distance(speciment):
|
||||
|
||||
# tournament selection
|
||||
# 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
|
||||
selection_ix = randint(len(pop))
|
||||
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
|
||||
# if gene is mutated then it is swapped with randomly chosen gene from the same speciment
|
||||
def mutation(speciment, r_mut):
|
||||
for i in range(len(speciment)-1):
|
||||
for i in range(len(speciment)):
|
||||
# check for a mutation
|
||||
if rand() < r_mut:
|
||||
# flip the bit
|
||||
@ -126,12 +126,12 @@ if __name__ == "__main__":
|
||||
# crossover rate
|
||||
r_cross = 0.9
|
||||
# mutation rate
|
||||
r_mut = 0.05
|
||||
r_mut = 0.15
|
||||
|
||||
# create new minefield instance
|
||||
import os
|
||||
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
|
||||
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 algorithms.search.a_star import State, graphsearch
|
||||
from objects.mine_models.chained_mine import ChainedMine
|
||||
from objects.mine_models.time_mine import TimeMine
|
||||
|
||||
|
||||
def get_score(minefield, speciment):
|
||||
initial_state = State(row=0, column=0, direction=Direction.RIGHT)
|
||||
score = 0
|
||||
def possible_states(row, column):
|
||||
possible_states = []
|
||||
|
||||
for el_index in range(len(speciment) - 1):
|
||||
action_sequence, initial_state, cost = \
|
||||
graphsearch(initial_state,
|
||||
if Minefield.is_valid_move(row + 1, column):
|
||||
possible_states.append(State(row + 1, column, Direction.UP))
|
||||
|
||||
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,
|
||||
target_type="mine",
|
||||
tox=speciment[el_index][0],
|
||||
toy=speciment[el_index][1],
|
||||
tox=mine[0],
|
||||
toy=mine[1],
|
||||
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:
|
||||
cost += 10000
|
||||
for mine1 in mines:
|
||||
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):
|
||||
minefield.next_turn()
|
||||
return dict_table
|
||||
|
||||
score += cost
|
||||
|
||||
score += 10000 * minefield.explosions
|
||||
return score
|
||||
def get_score(minefield, speciment, table=None):
|
||||
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):
|
||||
@ -43,6 +142,6 @@ def get_mines_coords(minefield: Minefield):
|
||||
mine = minefield.matrix[row][column].mine
|
||||
|
||||
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)
|
||||
|
||||
# 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):
|
||||
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 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
|
||||
|
||||
@ -141,11 +141,14 @@ class Game:
|
||||
def run_genetics(self):
|
||||
genetics_minefield = Minefield(const.MAP_RANDOM_10x10)
|
||||
|
||||
sequence, score = \
|
||||
genetic_algorithm.genetic_algorithm(genetics_minefield, helpers.get_score, 10, 100, 0.9, 0.05)
|
||||
sequence = \
|
||||
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
|
||||
|
||||
def set_next_genetic_target(self):
|
||||
|
@ -31,8 +31,11 @@ class Agent:
|
||||
|
||||
@staticmethod
|
||||
def defuse_a_mine(mine):
|
||||
is_success = popup.disarming_popup(mine)
|
||||
return is_success
|
||||
if mine.active:
|
||||
is_success = popup.disarming_popup(mine)
|
||||
return is_success
|
||||
else:
|
||||
return True
|
||||
|
||||
def update_and_draw(self, window, delta_time, minefield):
|
||||
self.update(delta_time, minefield)
|
||||
|
@ -11,6 +11,7 @@ class TimeMine(Mine):
|
||||
|
||||
def disarm(self, wire):
|
||||
if self.active:
|
||||
self.starting_time = 0
|
||||
return super().disarm(wire)
|
||||
else:
|
||||
# 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)
|
||||
|
||||
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
|
||||
if terrain_type == "CONCRETE":
|
||||
return Terrain.CONCRETE
|
||||
|
@ -162,6 +162,6 @@ HIGHLIGHT.set_alpha(100)
|
||||
# ==== 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",
|
||||
"mine": {
|
||||
"mine_type": "time",
|
||||
"timer": 320
|
||||
"timer": 120
|
||||
}
|
||||
},
|
||||
"1,0": {
|
||||
@ -154,7 +154,7 @@
|
||||
"terrain": "GRASS",
|
||||
"mine": {
|
||||
"mine_type": "time",
|
||||
"timer": 40
|
||||
"timer": 30
|
||||
}
|
||||
},
|
||||
"3,2": {
|
||||
@ -363,7 +363,7 @@
|
||||
"terrain": "MUD",
|
||||
"mine": {
|
||||
"mine_type": "time",
|
||||
"timer": 240
|
||||
"timer": 140
|
||||
}
|
||||
},
|
||||
"7,7": {
|
||||
@ -386,7 +386,7 @@
|
||||
"terrain": "MUD",
|
||||
"mine": {
|
||||
"mine_type": "time",
|
||||
"timer": 150
|
||||
"timer": 60
|
||||
}
|
||||
},
|
||||
"8,2": {
|
||||
|
Loading…
Reference in New Issue
Block a user