coordinated all changes regarding decision_tree functionality

This commit is contained in:
JakubR 2021-05-23 20:20:02 +02:00
parent 9b20be5248
commit f6ff6e548c
16 changed files with 20139 additions and 20299 deletions

View File

@ -4,7 +4,8 @@ from joblib import dump, load
from sklearn import tree
from sklearn.feature_extraction import DictVectorizer
from mines.disarming.mine_parameters import MineParameters
from objects.mines.disarming.mine_parameters import MineParameters
from objects.mines.disarming.parameter_json import generate_data
class DecisionTree:
@ -61,7 +62,7 @@ class DecisionTree:
print(f"Answer: {answer}\nCorrect: {correct}")
mistakes += 1
print(f"Accuracy: {100 - (mistakes / 1000)}")
print(f"Accuracy: {100 - (mistakes / 10)}")
@staticmethod
def _process_input_line(line):
@ -74,7 +75,8 @@ class DecisionTree:
if __name__ == "__main__":
# generate_data("training_set.txt", 20000)
decision_tree = DecisionTree()
decision_tree.build("params3.txt", 15)
decision_tree.build("training_set.txt", 15)
decision_tree.test()
decision_tree.save()

25
game.py
View File

@ -114,15 +114,21 @@ class Game:
# draws a random mine to disarm (in auto mode)
def set_random_mine_as_target(self):
self.goal = choice(self.minefield.get_active_mines()).position
if any(self.minefield.get_active_mines()):
self.goal = choice(self.minefield.get_active_mines()).position
# display new destination
self.input_box_row.set_texts(user_input=str(self.goal[0]))
self.input_box_column.set_texts(user_input=str(self.goal[1]))
# display new destination
self.input_box_row.set_texts(user_input=str(self.goal[0]))
self.input_box_column.set_texts(user_input=str(self.goal[1]))
# prevents highlighting input_box_row,
# couldn't find any better solution w/o major Game class changes
self.input_box_row.set_is_selected(False)
# prevents highlighting input_box_row,
# couldn't find any better solution w/o major Game class changes
self.input_box_row.set_is_selected(False)
return True
else:
return False
# gets action sequence for agent
def get_action_sequence(self, target_type: str = "tile"):
@ -138,6 +144,11 @@ class Game:
toy=self.goal[1]
)
# returns a mine on a given position
def get_mine(self, position):
row, column = position
return self.minefield.matrix[row][column].mine
# initializes attributes before game loop begins
def initialize_before_game_loop(self):
self.agent_action = None

19
main.py
View File

@ -71,7 +71,7 @@ def main():
# getting action sequence for agent
if auto and running:
in_menu = False
game.set_random_mine_as_target()
auto = game.set_random_mine_as_target()
action_sequence = game.get_action_sequence("mine")
elif running:
@ -125,15 +125,23 @@ def main():
# clean up after game loop
game.agent_take_last_action()
game.cleanup_after_game_loop()
game.draw_minefield()
pygame.display.flip()
if auto:
if not game.agent.defuse_a_mine(game.get_mine(game.goal)):
print("BOOOOOOM\n\n")
is_game_over = True
else:
print("guess you will live a little longer...\n\n")
# reset in_menu flag
in_menu = True
is_game_over = game.time_mine_exploded()
# TODO temporarily disabling game over screen
# if you want to enable game over comment line below
is_game_over = False
# if you want to enable game over uncomment line below
# is_game_over = game.time_mine_exploded()
while running and is_game_over:
events = pygame.event.get()
@ -152,6 +160,7 @@ def main():
game.cleanup_after_game_loop()
is_game_over = False
in_menu = True
auto = False
# updating graphics
pygame.display.flip()

View File

@ -1,7 +1,9 @@
import project_constants as const
from assets import asset_constants as asset
import json
from time import sleep
from pygame import transform
from algorithms.learn.decision_tree import DecisionTree
# Class of our agent, initialization of it
@ -19,13 +21,22 @@ class Agent:
self.row, self.column = int(self.row), int(self.column)
self.position = [self.row, self.column]
self.on_screen_coordinates = const.get_tile_coordinates(tuple(self.position))
# self.direction = const.Direction()
self.decision_tree = DecisionTree(const.ROOT_DIR + "/algorithms/learn/decision_tree.joblib",
const.ROOT_DIR + "/algorithms/learn/dict_vectorizer.joblib")
self.direction = const.Direction(data["agents_initial_state"]["direction"])
self.rotation_angle = -const.Direction(self.direction).value * 90
self.going_forward = False
self.rotating_left = False
self.rotating_right = False
def defuse_a_mine(self, mine):
mine_params = mine.investigate()
chosen_wire = self.decision_tree.get_answer(mine_params)
# TODO temporarily printing chosen wire
print("agent's chosen wire: " + str(chosen_wire[0]))
sleep(3)
return mine.disarm(chosen_wire)
def update_and_draw(self, window, delta_time, minefield):
self.update(delta_time, minefield)
self.draw(window)

View File

@ -18,18 +18,19 @@ class DangerClassHash(Enum):
WEAPON_OF_MASS_DESTRUCTION = 32, "weapon of mass destruction"
RADIOACTIVE = 16, "radioactive"
CASUAL_DEVASTATOR = 8, "casual devastator"
LITTLE_BOY = 4, "little boy"
CHERRY_BOMB = 0, "cherry bomb"
class SeriesHash(Enum):
TCH_2990TONER = 65, "TCH_2990toner"
TCH_2990TONER = 128, "TCH_2990toner"
TCH_2990INKJET = 64, "TCH_2990inkjet"
TVY_2400H = 55, "TVY_2400h"
SWX_5000 = 53, "SWX_5000"
SWX_4000 = 50, "SWX_4000"
WORKHORSE_3200 = 43, "WORKHORSE_3200"
FX_500 = 40, "FX_500"
TVY_2400 = 23, "TVY_2400"
TVY_2400H = 48, "TVY_2400h"
SWX_5000 = 32, "SWX_5000"
SWX_4000 = 16, "SWX_4000"
WORKHORSE_3200 = 8, "WORKHORSE_3200"
FX_500 = 4, "FX_500"
TVY_2400 = 0, "TVY_2400"
class IndicatorHash(Enum):
@ -50,11 +51,20 @@ class SpecificityHash(Enum):
FRAGMENTATION_MINE = 0, "fragmentation_mine"
class WeightHash(Enum):
FAT_MAN = 32, "fat_man"
EXTRA_LARGE = 24, "extra_large"
TOTAL_AVERAGE = 16, "total_average"
SLIM_FIT = 8, "slim_fit"
BREAD_CRUMB = 0, "bread_crumb"
MAX_VALUE = max([elem.value[0] for elem in TypeHash]) \
+ max([elem.value[0] for elem in DangerClassHash]) \
+ max([elem.value[0] for elem in SeriesHash]) \
+ max([elem.value[0] for elem in IndicatorHash]) \
+ max([elem.value[0] for elem in SpecificityHash])
+ max([elem.value[0] for elem in SpecificityHash]) \
+ max([elem.value[0] for elem in WeightHash])
def _get_wire_color(hash_sum):
@ -67,15 +77,16 @@ def _get_wire_color(hash_sum):
# STRING ARGUMENTS
def get_wire_from_str(mine_type: str, danger_cls: str, series: str, indicator: str, specificity: str):
def get_wire_from_str(mine_type: str, danger_cls: str, series: str, indicator: str, specificity: str, weight: str):
type_hash = TypeHash[mine_type.upper().replace(" ", "_")].value[0]
danger_cls_hash = DangerClassHash[danger_cls.upper().replace(" ", "_")].value[0]
series_hash = SeriesHash[series.upper().replace(" ", "_")].value[0]
indicator_hash = IndicatorHash[indicator.upper().replace(" ", "_")].value[0]
specificity_hash = SpecificityHash[specificity.upper().replace(" ", "_")].value[0]
weight_hash = WeightHash[weight.upper().replace(" ", "_")].value[0]
hash_sum = type_hash + danger_cls_hash + series_hash + indicator_hash + specificity_hash
hash_sum = type_hash + danger_cls_hash + series_hash + indicator_hash + specificity_hash + weight_hash
return _get_wire_color(hash_sum)
@ -85,7 +96,10 @@ def get_wire_from_enums(
danger_cls: DangerClassHash,
series: SeriesHash,
indicator: IndicatorHash,
specificity: SpecificityHash):
specificity: SpecificityHash,
weight: WeightHash):
hash_list = [mine_type, danger_cls, series, indicator, specificity, weight]
hash_sum = sum([enum.value[0] for enum in hash_list])
hash_sum = mine_type.value[0] + danger_cls.value[0] + series.value[0] + indicator.value[0] + specificity.value[0]
return _get_wire_color(hash_sum)

View File

@ -1,5 +1,5 @@
import random
from mines.disarming import hash_function as hf
from objects.mines.disarming import hash_function as hf
class MineParameters:
@ -11,20 +11,22 @@ class MineParameters:
self.series = random.choice(list(hf.SeriesHash))
self.indicator = random.choice(list(hf.IndicatorHash))
self.specificity = random.choice(list(hf.SpecificityHash))
self.weight = random.choice(list(hf.WeightHash))
else:
self.mine_type = jdict["mine_type"]
self.danger_cls = jdict["danger_cls"]
self.series = jdict["series"]
self.specificity = jdict["specificity"]
self.indicator = jdict["indicator"]
self.weight = jdict["weight"]
if mine_type is not None:
self.mine_type = mine_type
def jsonifyable_dict(self):
def jsonifyable_dict(self, with_wire=True):
wire = hf.get_wire_from_enums(
self.mine_type, self.danger_cls, self.series,
self.indicator, self.specificity
self.indicator, self.specificity, self.weight
)
jdict = {
@ -33,13 +35,17 @@ class MineParameters:
"series": self.series.value[1],
"specificity": self.specificity.value[1],
"indicator": self.indicator.value[1],
"wire": wire.value[1]
"weight": self.weight.value[1]
}
if with_wire:
jdict["wire"] = wire.value[1]
return jdict
def get_parameters(self):
return self.mine_type, self.danger_cls, self.series,\
self.specificity, self.indicator
self.specificity, self.indicator, self.weight

View File

@ -1,9 +1,10 @@
import json
import objects.mines.disarming.mine_parameters as param
import os
import project_constants as const
# this module is self contained, used to generate a json file
DIR_DATA = os.path.join("../../../resources", "data")
DIR_DATA = os.path.join(const.ROOT_DIR, "resources", "data")
# just to show, how mine parameters works
@ -40,7 +41,7 @@ def generate_data(file_name: str, lines: int):
def main():
generate_data("params4.txt", 1000)
generate_data("training_set.txt", 20000)
if __name__ == "__main__":

View File

@ -2,17 +2,21 @@
from __future__ import annotations
from .mine import Mine
from objects.mines.disarming.hash_function import TypeHash
class ChainedMine(Mine):
def __init__(self, position, predecessor: ChainedMine = None, active=True):
self.predecessor = predecessor
self.type = "chained"
super().__init__(position, active)
self.predecessor = predecessor
super().__init__(TypeHash.CHAINED, position, active)
def disarm(self):
def disarm(self, wire):
if self.predecessor is None or not self.predecessor.active:
super().disarm()
return super().disarm(wire)
else:
# boom?
pass
return False
def investigate(self):
return super().investigate()

View File

@ -4,16 +4,37 @@ from abc import ABC, abstractmethod
# type hints
from typing import Tuple
from objects.mines.disarming.mine_parameters import MineParameters
# Mine cannot be instantiated
# all abstract methods must be implemented in derived classes
class Mine(ABC):
@abstractmethod
def __init__(self, position: Tuple[int, int], active=True):
def __init__(self, _type, position: Tuple[int, int], active=True):
self.enum_type = _type
self.position = position
self.wire = None
self.active = active
@abstractmethod
def disarm(self):
self.active = False
def disarm(self, wire):
if wire == self.wire:
self.active = False
return True
else:
return False
@abstractmethod
def investigate(self):
mine_parameters = MineParameters(mine_type=self.enum_type).jsonifyable_dict()
wire = mine_parameters["wire"]
del mine_parameters["wire"]
self.wire = wire
# TODO temporarily printing parameters and right wire
print("parameters:", mine_parameters, "\nright wire: " + wire)
return mine_parameters

View File

@ -1,10 +1,14 @@
from .mine import Mine
from objects.mines.disarming.hash_function import TypeHash
class StandardMine(Mine):
def __init__(self, position, active=True):
self.type = "standard"
super().__init__(position, active)
super().__init__(TypeHash.STANDARD, position, active)
def disarm(self):
super().disarm()
def disarm(self, wire):
return super().disarm(wire)
def investigate(self):
return super().investigate()

View File

@ -1,4 +1,5 @@
from .mine import Mine
from objects.mines.disarming.hash_function import TypeHash
class TimeMine(Mine):
@ -6,7 +7,10 @@ class TimeMine(Mine):
self.type = "time"
self.timer = timer
self.starting_time = timer
super().__init__(position, active)
super().__init__(TypeHash.TIME, position, active)
def disarm(self):
super().disarm()
def disarm(self, wire):
return super().disarm(wire)
def investigate(self):
return super().investigate()

View File

@ -21,7 +21,8 @@ from ui.input_box import InputBox
V_NAME_OF_WINDOW = "MineFusion TM"
V_FPS = 60
DIR_ASSETS = os.path.join("resources", "assets")
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
DIR_ASSETS = os.path.join(ROOT_DIR, "resources", "assets")
TURN_INTERVAL = 0.3 # interval between two turns in seconds
@ -157,54 +158,6 @@ HIGHLIGHT = pygame.transform.scale(
)
HIGHLIGHT.set_alpha(100)
_gui_width = V_SIDE_MENU_WIDTH
_ib_height, _bt_height = V_INPUT_BOX_HEIGHT, V_BUTTON_HEIGHT
_gui_x = V_TILE_AREA_WIDTH + 2 * V_SCREEN_PADDING + V_NUMBER_PADDING
_gui_y = SCREEN.get_height() / 2 - (2 * _ib_height + 2 * _bt_height + 30) / 2
INPUT_ROW = InputBox(
position=(_gui_x, _gui_y),
dimensions=(_gui_width, _ib_height),
text="row",
box_color=(100, 200, 100),
bottom_strip_color=(120, 220, 120),
inner_box_color=(120, 220, 120),
outline_color=(80, 180, 80),
outline_additional_pixel=True,
valid_input_characters="1234567890",
input_centered=True,
clear_input_on_click=True
)
INPUT_COLUMN = InputBox(
position=(_gui_x, _gui_y + _ib_height + 10),
dimensions=(_gui_width, _ib_height),
text="column",
box_color=(100, 200, 100),
bottom_strip_color=(120, 220, 120),
inner_box_color=(120, 220, 120),
outline_color=(80, 180, 80),
outline_additional_pixel=True,
valid_input_characters="1234567890",
input_centered=True,
clear_input_on_click=True
)
RANDOM_BUTTON = Button(
position=(_gui_x, _gui_y + 2 * _ib_height + 20),
dimensions=(_gui_width, _bt_height),
text="random",
box_color=(100, 200, 100),
outline_color=(80, 180, 80),
outline_additional_pixel=True
)
OK_BUTTON = Button(
position=(_gui_x, _gui_y + 2 * _ib_height + _bt_height + 30),
dimensions=(_gui_width, _bt_height),
text="ok",
box_color=(100, 200, 100),
outline_color=(80, 180, 80),
outline_additional_pixel=True
)
# ============== #
# ==== MAPS ==== #

View File

@ -1,200 +0,0 @@
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "SWX_5000", "specificity": "depth_mine", "indicator": "blue", "wire": "green"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "FX_500", "specificity": "fragmentation_mine", "indicator": "white", "wire": "green"}
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "TCH_2990inkjet", "specificity": "anti_tank", "indicator": "red", "wire": "green"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "anti_tank", "indicator": "red", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "big bang", "series": "SWX_5000", "specificity": "proximity_mine", "indicator": "green", "wire": "green"}
{"mine_type": "time", "danger_cls": "weapon of mass destruction", "series": "TVY_2400h", "specificity": "proximity_mine", "indicator": "red", "wire": "red"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "SWX_4000", "specificity": "pressure_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "WORKHORSE_3200", "specificity": "fragmentation_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "time", "danger_cls": "weapon of mass destruction", "series": "TVY_2400", "specificity": "anti_tank", "indicator": "green", "wire": "red"}
{"mine_type": "time", "danger_cls": "big bang", "series": "SWX_4000", "specificity": "fragmentation_mine", "indicator": "red", "wire": "red"}
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "TCH_2990toner", "specificity": "anti_tank", "indicator": "white", "wire": "green"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "TVY_2400", "specificity": "anti_aircraft", "indicator": "blue", "wire": "red"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "SWX_4000", "specificity": "anti_tank", "indicator": "green", "wire": "green"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "SWX_4000", "specificity": "anti_tank", "indicator": "red", "wire": "blue"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "TCH_2990inkjet", "specificity": "proximity_mine", "indicator": "blue", "wire": "red"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "TCH_2990toner", "specificity": "anti_tank", "indicator": "blue", "wire": "red"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "TVY_2400", "specificity": "anti_aircraft", "indicator": "red", "wire": "blue"}
{"mine_type": "time", "danger_cls": "weapon of mass destruction", "series": "TVY_2400", "specificity": "anti_tank", "indicator": "red", "wire": "red"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "TVY_2400", "specificity": "pressure_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "TVY_2400", "specificity": "proximity_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "FX_500", "specificity": "anti_tank", "indicator": "blue", "wire": "blue"}
{"mine_type": "time", "danger_cls": "weapon of mass destruction", "series": "SWX_5000", "specificity": "anti_tank", "indicator": "blue", "wire": "red"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "TVY_2400", "specificity": "pressure_mine", "indicator": "red", "wire": "green"}
{"mine_type": "time", "danger_cls": "big bang", "series": "SWX_4000", "specificity": "anti_personnel", "indicator": "blue", "wire": "red"}
{"mine_type": "time", "danger_cls": "big bang", "series": "TVY_2400", "specificity": "proximity_mine", "indicator": "red", "wire": "red"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "SWX_4000", "specificity": "anti_tank", "indicator": "white", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "TVY_2400h", "specificity": "pressure_mine", "indicator": "green", "wire": "blue"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "TCH_2990toner", "specificity": "pressure_mine", "indicator": "white", "wire": "red"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "SWX_5000", "specificity": "anti_tank", "indicator": "white", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "FX_500", "specificity": "anti_personnel", "indicator": "blue", "wire": "green"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "FX_500", "specificity": "proximity_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "TVY_2400h", "specificity": "proximity_mine", "indicator": "green", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "TVY_2400h", "specificity": "anti_personnel", "indicator": "green", "wire": "green"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "anti_aircraft", "indicator": "red", "wire": "red"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "TVY_2400", "specificity": "fragmentation_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "TVY_2400h", "specificity": "pressure_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "WORKHORSE_3200", "specificity": "anti_tank", "indicator": "red", "wire": "red"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "TVY_2400h", "specificity": "anti_tank", "indicator": "red", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "TVY_2400h", "specificity": "proximity_mine", "indicator": "yellow", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "casual devastator", "series": "TVY_2400", "specificity": "proximity_mine", "indicator": "yellow", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "FX_500", "specificity": "fragmentation_mine", "indicator": "yellow", "wire": "blue"}
{"mine_type": "time", "danger_cls": "weapon of mass destruction", "series": "TCH_2990inkjet", "specificity": "depth_mine", "indicator": "yellow", "wire": "red"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "TCH_2990inkjet", "specificity": "depth_mine", "indicator": "white", "wire": "red"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "TCH_2990toner", "specificity": "pressure_mine", "indicator": "yellow", "wire": "red"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "TVY_2400", "specificity": "anti_tank", "indicator": "green", "wire": "blue"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "FX_500", "specificity": "anti_personnel", "indicator": "yellow", "wire": "red"}
{"mine_type": "chained", "danger_cls": "radioactive", "series": "SWX_4000", "specificity": "depth_mine", "indicator": "green", "wire": "green"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "FX_500", "specificity": "fragmentation_mine", "indicator": "green", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "radioactive", "series": "TCH_2990toner", "specificity": "anti_tank", "indicator": "yellow", "wire": "green"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "TVY_2400h", "specificity": "anti_personnel", "indicator": "green", "wire": "green"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "TVY_2400", "specificity": "anti_aircraft", "indicator": "white", "wire": "red"}
{"mine_type": "time", "danger_cls": "weapon of mass destruction", "series": "TCH_2990toner", "specificity": "pressure_mine", "indicator": "blue", "wire": "red"}
{"mine_type": "standard", "danger_cls": "big bang", "series": "TCH_2990inkjet", "specificity": "anti_personnel", "indicator": "red", "wire": "red"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "TCH_2990inkjet", "specificity": "anti_personnel", "indicator": "green", "wire": "red"}
{"mine_type": "standard", "danger_cls": "casual devastator", "series": "SWX_5000", "specificity": "anti_aircraft", "indicator": "green", "wire": "green"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "TVY_2400", "specificity": "depth_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "fragmentation_mine", "indicator": "blue", "wire": "blue"}
{"mine_type": "time", "danger_cls": "weapon of mass destruction", "series": "SWX_5000", "specificity": "anti_aircraft", "indicator": "red", "wire": "red"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "TCH_2990inkjet", "specificity": "anti_personnel", "indicator": "yellow", "wire": "red"}
{"mine_type": "chained", "danger_cls": "radioactive", "series": "TVY_2400", "specificity": "anti_tank", "indicator": "blue", "wire": "blue"}
{"mine_type": "time", "danger_cls": "weapon of mass destruction", "series": "TVY_2400h", "specificity": "fragmentation_mine", "indicator": "green", "wire": "red"}
{"mine_type": "standard", "danger_cls": "casual devastator", "series": "SWX_4000", "specificity": "anti_personnel", "indicator": "green", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "casual devastator", "series": "FX_500", "specificity": "anti_tank", "indicator": "white", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "WORKHORSE_3200", "specificity": "anti_aircraft", "indicator": "red", "wire": "green"}
{"mine_type": "standard", "danger_cls": "casual devastator", "series": "TCH_2990inkjet", "specificity": "anti_tank", "indicator": "white", "wire": "blue"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "SWX_4000", "specificity": "pressure_mine", "indicator": "green", "wire": "green"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "TCH_2990toner", "specificity": "anti_personnel", "indicator": "green", "wire": "red"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "FX_500", "specificity": "fragmentation_mine", "indicator": "yellow", "wire": "green"}
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "TCH_2990toner", "specificity": "anti_personnel", "indicator": "red", "wire": "green"}
{"mine_type": "standard", "danger_cls": "casual devastator", "series": "TVY_2400h", "specificity": "anti_aircraft", "indicator": "green", "wire": "green"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "WORKHORSE_3200", "specificity": "depth_mine", "indicator": "green", "wire": "blue"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "FX_500", "specificity": "anti_aircraft", "indicator": "red", "wire": "red"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "FX_500", "specificity": "pressure_mine", "indicator": "yellow", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "WORKHORSE_3200", "specificity": "proximity_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "TVY_2400", "specificity": "pressure_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "TVY_2400h", "specificity": "anti_tank", "indicator": "red", "wire": "green"}
{"mine_type": "time", "danger_cls": "big bang", "series": "TVY_2400", "specificity": "depth_mine", "indicator": "white", "wire": "red"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "SWX_4000", "specificity": "anti_tank", "indicator": "blue", "wire": "green"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "WORKHORSE_3200", "specificity": "depth_mine", "indicator": "blue", "wire": "green"}
{"mine_type": "time", "danger_cls": "weapon of mass destruction", "series": "TCH_2990inkjet", "specificity": "proximity_mine", "indicator": "green", "wire": "red"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "WORKHORSE_3200", "specificity": "anti_personnel", "indicator": "red", "wire": "red"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "TCH_2990toner", "specificity": "pressure_mine", "indicator": "blue", "wire": "blue"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "WORKHORSE_3200", "specificity": "proximity_mine", "indicator": "white", "wire": "green"}
{"mine_type": "time", "danger_cls": "big bang", "series": "SWX_4000", "specificity": "pressure_mine", "indicator": "blue", "wire": "red"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "TCH_2990toner", "specificity": "anti_tank", "indicator": "yellow", "wire": "red"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "SWX_5000", "specificity": "depth_mine", "indicator": "green", "wire": "red"}
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "WORKHORSE_3200", "specificity": "anti_personnel", "indicator": "yellow", "wire": "green"}
{"mine_type": "time", "danger_cls": "big bang", "series": "TCH_2990inkjet", "specificity": "anti_tank", "indicator": "white", "wire": "red"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "pressure_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "SWX_4000", "specificity": "proximity_mine", "indicator": "blue", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "anti_tank", "indicator": "red", "wire": "blue"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "depth_mine", "indicator": "blue", "wire": "red"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "WORKHORSE_3200", "specificity": "fragmentation_mine", "indicator": "green", "wire": "green"}
{"mine_type": "standard", "danger_cls": "casual devastator", "series": "TVY_2400", "specificity": "anti_aircraft", "indicator": "red", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "TCH_2990inkjet", "specificity": "anti_personnel", "indicator": "red", "wire": "green"}
{"mine_type": "time", "danger_cls": "weapon of mass destruction", "series": "SWX_4000", "specificity": "fragmentation_mine", "indicator": "yellow", "wire": "red"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "TCH_2990inkjet", "specificity": "pressure_mine", "indicator": "blue", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "FX_500", "specificity": "proximity_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "time", "danger_cls": "big bang", "series": "TCH_2990toner", "specificity": "pressure_mine", "indicator": "white", "wire": "red"}
{"mine_type": "time", "danger_cls": "big bang", "series": "FX_500", "specificity": "anti_personnel", "indicator": "red", "wire": "red"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "FX_500", "specificity": "fragmentation_mine", "indicator": "blue", "wire": "green"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "SWX_4000", "specificity": "fragmentation_mine", "indicator": "green", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "casual devastator", "series": "WORKHORSE_3200", "specificity": "proximity_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "TVY_2400h", "specificity": "pressure_mine", "indicator": "yellow", "wire": "green"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "pressure_mine", "indicator": "yellow", "wire": "green"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "TCH_2990toner", "specificity": "depth_mine", "indicator": "green", "wire": "green"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "WORKHORSE_3200", "specificity": "pressure_mine", "indicator": "blue", "wire": "green"}
{"mine_type": "standard", "danger_cls": "casual devastator", "series": "WORKHORSE_3200", "specificity": "pressure_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "big bang", "series": "SWX_4000", "specificity": "pressure_mine", "indicator": "red", "wire": "green"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "FX_500", "specificity": "depth_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "TCH_2990inkjet", "specificity": "anti_aircraft", "indicator": "white", "wire": "red"}
{"mine_type": "time", "danger_cls": "big bang", "series": "FX_500", "specificity": "pressure_mine", "indicator": "blue", "wire": "red"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "TCH_2990inkjet", "specificity": "proximity_mine", "indicator": "blue", "wire": "red"}
{"mine_type": "chained", "danger_cls": "radioactive", "series": "TCH_2990inkjet", "specificity": "anti_personnel", "indicator": "yellow", "wire": "green"}
{"mine_type": "standard", "danger_cls": "casual devastator", "series": "WORKHORSE_3200", "specificity": "anti_tank", "indicator": "blue", "wire": "blue"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "FX_500", "specificity": "depth_mine", "indicator": "white", "wire": "red"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "FX_500", "specificity": "anti_tank", "indicator": "red", "wire": "red"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "FX_500", "specificity": "anti_tank", "indicator": "green", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "TVY_2400", "specificity": "anti_aircraft", "indicator": "yellow", "wire": "green"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "TVY_2400h", "specificity": "pressure_mine", "indicator": "yellow", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "SWX_5000", "specificity": "pressure_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "radioactive", "series": "FX_500", "specificity": "fragmentation_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "TCH_2990toner", "specificity": "fragmentation_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "big bang", "series": "SWX_4000", "specificity": "depth_mine", "indicator": "blue", "wire": "green"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "SWX_5000", "specificity": "anti_tank", "indicator": "red", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "SWX_4000", "specificity": "depth_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "radioactive", "series": "SWX_5000", "specificity": "proximity_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "FX_500", "specificity": "proximity_mine", "indicator": "green", "wire": "green"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "SWX_4000", "specificity": "pressure_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "pressure_mine", "indicator": "blue", "wire": "green"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "TVY_2400h", "specificity": "anti_personnel", "indicator": "blue", "wire": "green"}
{"mine_type": "standard", "danger_cls": "big bang", "series": "SWX_5000", "specificity": "anti_tank", "indicator": "yellow", "wire": "green"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "TCH_2990inkjet", "specificity": "fragmentation_mine", "indicator": "green", "wire": "green"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "SWX_4000", "specificity": "anti_personnel", "indicator": "white", "wire": "red"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "TVY_2400", "specificity": "anti_aircraft", "indicator": "white", "wire": "green"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "TCH_2990toner", "specificity": "fragmentation_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "radioactive", "series": "SWX_4000", "specificity": "depth_mine", "indicator": "green", "wire": "green"}
{"mine_type": "time", "danger_cls": "big bang", "series": "SWX_4000", "specificity": "depth_mine", "indicator": "yellow", "wire": "red"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "TVY_2400h", "specificity": "proximity_mine", "indicator": "green", "wire": "green"}
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "TCH_2990inkjet", "specificity": "anti_personnel", "indicator": "green", "wire": "green"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "FX_500", "specificity": "anti_tank", "indicator": "yellow", "wire": "red"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "TVY_2400", "specificity": "fragmentation_mine", "indicator": "yellow", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "TVY_2400", "specificity": "fragmentation_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "time", "danger_cls": "big bang", "series": "WORKHORSE_3200", "specificity": "anti_aircraft", "indicator": "yellow", "wire": "red"}
{"mine_type": "time", "danger_cls": "big bang", "series": "TVY_2400h", "specificity": "fragmentation_mine", "indicator": "blue", "wire": "red"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "SWX_4000", "specificity": "anti_personnel", "indicator": "green", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "weapon of mass destruction", "series": "TCH_2990toner", "specificity": "anti_tank", "indicator": "green", "wire": "green"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "TCH_2990inkjet", "specificity": "anti_aircraft", "indicator": "green", "wire": "green"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "TVY_2400h", "specificity": "anti_personnel", "indicator": "yellow", "wire": "green"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "WORKHORSE_3200", "specificity": "anti_aircraft", "indicator": "white", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "TVY_2400", "specificity": "depth_mine", "indicator": "blue", "wire": "green"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "TCH_2990inkjet", "specificity": "depth_mine", "indicator": "white", "wire": "red"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "SWX_5000", "specificity": "depth_mine", "indicator": "white", "wire": "green"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "pressure_mine", "indicator": "blue", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "TVY_2400h", "specificity": "proximity_mine", "indicator": "blue", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "cherry bomb", "series": "TCH_2990inkjet", "specificity": "depth_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "SWX_4000", "specificity": "proximity_mine", "indicator": "blue", "wire": "blue"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "depth_mine", "indicator": "white", "wire": "red"}
{"mine_type": "standard", "danger_cls": "big bang", "series": "TCH_2990inkjet", "specificity": "anti_personnel", "indicator": "green", "wire": "red"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "TCH_2990inkjet", "specificity": "pressure_mine", "indicator": "red", "wire": "blue"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "TCH_2990inkjet", "specificity": "anti_aircraft", "indicator": "yellow", "wire": "red"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "WORKHORSE_3200", "specificity": "anti_personnel", "indicator": "yellow", "wire": "green"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "WORKHORSE_3200", "specificity": "pressure_mine", "indicator": "yellow", "wire": "green"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "SWX_4000", "specificity": "anti_aircraft", "indicator": "red", "wire": "red"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "WORKHORSE_3200", "specificity": "anti_personnel", "indicator": "red", "wire": "red"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "TCH_2990inkjet", "specificity": "fragmentation_mine", "indicator": "white", "wire": "green"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "anti_personnel", "indicator": "blue", "wire": "red"}
{"mine_type": "chained", "danger_cls": "big bang", "series": "SWX_4000", "specificity": "anti_personnel", "indicator": "blue", "wire": "red"}
{"mine_type": "chained", "danger_cls": "radioactive", "series": "FX_500", "specificity": "anti_aircraft", "indicator": "blue", "wire": "green"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "TCH_2990inkjet", "specificity": "anti_tank", "indicator": "yellow", "wire": "green"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "WORKHORSE_3200", "specificity": "anti_aircraft", "indicator": "blue", "wire": "red"}
{"mine_type": "time", "danger_cls": "big bang", "series": "TVY_2400", "specificity": "anti_tank", "indicator": "red", "wire": "red"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "TCH_2990toner", "specificity": "anti_tank", "indicator": "blue", "wire": "green"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "SWX_5000", "specificity": "anti_tank", "indicator": "green", "wire": "blue"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "SWX_5000", "specificity": "pressure_mine", "indicator": "blue", "wire": "green"}
{"mine_type": "chained", "danger_cls": "radioactive", "series": "SWX_5000", "specificity": "anti_tank", "indicator": "yellow", "wire": "green"}
{"mine_type": "time", "danger_cls": "big bang", "series": "FX_500", "specificity": "anti_tank", "indicator": "green", "wire": "red"}
{"mine_type": "time", "danger_cls": "big bang", "series": "SWX_4000", "specificity": "pressure_mine", "indicator": "green", "wire": "red"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "SWX_5000", "specificity": "proximity_mine", "indicator": "blue", "wire": "blue"}
{"mine_type": "time", "danger_cls": "cherry bomb", "series": "TVY_2400h", "specificity": "depth_mine", "indicator": "yellow", "wire": "red"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "WORKHORSE_3200", "specificity": "anti_aircraft", "indicator": "blue", "wire": "green"}
{"mine_type": "chained", "danger_cls": "radioactive", "series": "WORKHORSE_3200", "specificity": "fragmentation_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "SWX_5000", "specificity": "anti_tank", "indicator": "blue", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "big bang", "series": "TCH_2990inkjet", "specificity": "anti_personnel", "indicator": "green", "wire": "red"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "TVY_2400", "specificity": "anti_personnel", "indicator": "yellow", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "SWX_4000", "specificity": "anti_aircraft", "indicator": "blue", "wire": "green"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "WORKHORSE_3200", "specificity": "anti_aircraft", "indicator": "red", "wire": "green"}
{"mine_type": "standard", "danger_cls": "big bang", "series": "TCH_2990toner", "specificity": "anti_personnel", "indicator": "blue", "wire": "red"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "WORKHORSE_3200", "specificity": "pressure_mine", "indicator": "white", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "TCH_2990inkjet", "specificity": "anti_personnel", "indicator": "red", "wire": "green"}
{"mine_type": "time", "danger_cls": "big bang", "series": "SWX_4000", "specificity": "depth_mine", "indicator": "white", "wire": "red"}
{"mine_type": "standard", "danger_cls": "weapon of mass destruction", "series": "TVY_2400", "specificity": "anti_tank", "indicator": "white", "wire": "blue"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "TCH_2990inkjet", "specificity": "pressure_mine", "indicator": "blue", "wire": "blue"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "TVY_2400h", "specificity": "proximity_mine", "indicator": "green", "wire": "red"}
{"mine_type": "time", "danger_cls": "radioactive", "series": "FX_500", "specificity": "fragmentation_mine", "indicator": "white", "wire": "green"}
{"mine_type": "standard", "danger_cls": "radioactive", "series": "TCH_2990inkjet", "specificity": "anti_tank", "indicator": "red", "wire": "green"}
{"mine_type": "chained", "danger_cls": "casual devastator", "series": "SWX_4000", "specificity": "anti_aircraft", "indicator": "red", "wire": "green"}
{"mine_type": "time", "danger_cls": "casual devastator", "series": "WORKHORSE_3200", "specificity": "depth_mine", "indicator": "red", "wire": "red"}
{"mine_type": "standard", "danger_cls": "cherry bomb", "series": "TCH_2990inkjet", "specificity": "fragmentation_mine", "indicator": "blue", "wire": "blue"}
{"mine_type": "chained", "danger_cls": "radioactive", "series": "WORKHORSE_3200", "specificity": "pressure_mine", "indicator": "yellow", "wire": "blue"}

File diff suppressed because it is too large Load Diff