From f5f694df3ee668601a64228b7e9ec0d221e8942d Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Sun, 4 Oct 2020 17:52:27 +0200 Subject: [PATCH 01/20] construct utility buildings fix --- main.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index 59625a4..5a29db8 100644 --- a/main.py +++ b/main.py @@ -256,8 +256,10 @@ def something_needs_attention(): adjustEnergy(state.residences[edit_temp[1]]) return True elif building_under_construction is not None: #finish construction - print(building_under_construction) - if game_layer.game_state.residences[building_under_construction[2]].build_progress < 100: # TODO: inte ba kolla residence utan också utility + if (len(game_layer.game_state.residences) >= building_under_construction[2]) and (game_layer.game_state.residences[building_under_construction[2]].build_progress < 100): + game_layer.build((building_under_construction[0], building_under_construction[1])) + return True + elif (len(game_layer.game_state.utilities)-1 >= building_under_construction[2]) and (game_layer.game_state.utilities[building_under_construction[2]].build_progress < 100): game_layer.build((building_under_construction[0], building_under_construction[1])) return True else: From 0a8934c974602cf1f6327db72d1a03fa0116a083 Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Sun, 4 Oct 2020 17:54:10 +0200 Subject: [PATCH 02/20] testing buildings in develop --- main.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/main.py b/main.py index 5a29db8..70d74e9 100644 --- a/main.py +++ b/main.py @@ -270,13 +270,11 @@ def something_needs_attention(): def develop_society(): state = game_layer.game_state - if len(game_layer.game_state.residences) < 4: + if len(state.residences) < 5: build("Apartments") - elif len(game_layer.game_state.utilities) <1: - game_layer.place_foundation((3,6), "WindTurbine") - elif (state.utilities[0].build_progress < 100): - game_layer.build((3,6)) - elif state.funds > 25000 and len(game_layer.game_state.residences) < 7: + elif len(state.utilities) < 1: + build("WindTurbine") + elif state.funds > 25000 and len(game_layer.game_state.residences) < 11: build("HighRise") else: game_layer.wait() From 0833b843a38b997a7c4dbda1fd8ac9fdc915bdba Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Sun, 4 Oct 2020 17:54:41 +0200 Subject: [PATCH 03/20] check if structures are available before building --- main.py | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/main.py b/main.py index 70d74e9..0ab3454 100644 --- a/main.py +++ b/main.py @@ -287,22 +287,27 @@ def build(structure): for i in range(len(availableTiles)): if isinstance(availableTiles[i], tuple): game_layer.place_foundation(availableTiles[i], structure) - for j in range(len(state.residences)): - building = state.residences[j] - coords_to_check = (building.X, building.Y) - if coords_to_check == availableTiles[i]: - availableTiles[i] = building - building_under_construction = (building.X, building.Y, j) - rounds_between_energy = len(state.residences)+5 - return True - for j in range(len(state.utilities)): - building = state.utilities[j] - coords_to_check = (building.X, building.Y) - if coords_to_check == availableTiles[i]: - availableTiles[i] = building - building_under_construction = (building.X, building.Y, j) - rounds_between_energy = len(state.residences)+5 - return True + for building in state.available_residence_buildings: + if structure in building.building_name: + for j in range(len(state.residences)): + building = state.residences[j] + coords_to_check = (building.X, building.Y) + if coords_to_check == availableTiles[i]: + availableTiles[i] = building + building_under_construction = (building.X, building.Y, j) + rounds_between_energy = len(state.residences)+2 + return True + for building in state.available_utility_buildings: + if structure in building.building_name: + for j in range(len(state.utilities)): + building = state.utilities[j] + coords_to_check = (building.X, building.Y) + if coords_to_check == availableTiles[i]: + availableTiles[i] = building + building_under_construction = (building.X, building.Y, j) + rounds_between_energy = len(state.residences)+2 + return True + return False if __name__ == "__main__": From 143a5dbecff5f4d2810b6b65c9d32a2eecb06955 Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 16:41:09 +0200 Subject: [PATCH 04/20] flytta upp dev society & need attention i koden --- main.py | 72 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/main.py b/main.py index 0ab3454..24846f9 100644 --- a/main.py +++ b/main.py @@ -194,42 +194,6 @@ def take_turn(): for error in game_layer.game_state.errors: print("Error: " + error) - -def chartMap(): - state = game_layer.game_state - for x in range(len(state.map) - 1): - for y in range(len(state.map) - 1): - if state.map[x][y] == 0: - availableTiles.append((x, y)) - optimizeAvailableTiles() - -def adjustEnergy(currentBuilding): - global rounds_between_energy - global EMA_temp - blueprint = game_layer.get_residence_blueprint(currentBuilding.building_name) - outDoorTemp = game_layer.game_state.current_temp * 2 - EMA_temp - - temp_acceleration = (2*(21 - currentBuilding.temperature)/(rounds_between_energy)) - - effectiveEnergyIn = ((temp_acceleration - 0.04 * currentBuilding.current_pop + (currentBuilding.temperature - outDoorTemp) * blueprint.emissivity) / 0.75) + blueprint.base_energy_need - - if effectiveEnergyIn > blueprint.base_energy_need: - game_layer.adjust_energy_level((currentBuilding.X, currentBuilding.Y), effectiveEnergyIn) - elif effectiveEnergyIn < blueprint.base_energy_need: - game_layer.adjust_energy_level((currentBuilding.X, currentBuilding.Y), blueprint.base_energy_need + 0.01) - else: - print("you did it!") - game_layer.wait() - - - - - -def optimizeAvailableTiles(): - #hitta #utilities antal bästa platser i mitten av smeten och sätt de först, sätt allt runt dem i ordning så närmast är längst fram i listan - pass - - def something_needs_attention(): print("Checking for emergencies") global building_under_construction @@ -279,6 +243,42 @@ def develop_society(): else: game_layer.wait() +def chartMap(): + state = game_layer.game_state + for x in range(len(state.map) - 1): + for y in range(len(state.map) - 1): + if state.map[x][y] == 0: + availableTiles.append((x, y)) + optimizeAvailableTiles() + +def adjustEnergy(currentBuilding): + global rounds_between_energy + global EMA_temp + blueprint = game_layer.get_residence_blueprint(currentBuilding.building_name) + outDoorTemp = game_layer.game_state.current_temp * 2 - EMA_temp + + temp_acceleration = (2*(21 - currentBuilding.temperature)/(rounds_between_energy)) + + effectiveEnergyIn = ((temp_acceleration - 0.04 * currentBuilding.current_pop + (currentBuilding.temperature - outDoorTemp) * blueprint.emissivity) / 0.75) + blueprint.base_energy_need + + if effectiveEnergyIn > blueprint.base_energy_need: + game_layer.adjust_energy_level((currentBuilding.X, currentBuilding.Y), effectiveEnergyIn) + elif effectiveEnergyIn < blueprint.base_energy_need: + game_layer.adjust_energy_level((currentBuilding.X, currentBuilding.Y), blueprint.base_energy_need + 0.01) + else: + print("you did it!") + game_layer.wait() + + + + + +def optimizeAvailableTiles(): + #hitta #utilities antal bästa platser i mitten av smeten och sätt de först, sätt allt runt dem i ordning så närmast är längst fram i listan + pass + + + def build(structure): print("Building " + structure) state = game_layer.game_state From 8408f8f0a01bfb78292930face2d9ed10b9b39c2 Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 16:42:31 +0200 Subject: [PATCH 05/20] purge linus_taketurn code --- main.py | 92 --------------------------------------------------------- 1 file changed, 92 deletions(-) diff --git a/main.py b/main.py index 24846f9..93e8bb2 100644 --- a/main.py +++ b/main.py @@ -49,94 +49,6 @@ def main(): print("Done with game: " + game_layer.game_state.game_id) print("Final score was: " + str(game_layer.get_score()["finalScore"])) -def linus_take_turn(): - freeSpace = [] - - state = game_layer.game_state - for x in range(len(state.map)-1): - for y in range(len(state.map)-1): - if state.map[x][y] == 0: - freeSpace.append((x,y)) - - - #if (i == 0 or i%5 == 0)and i<26: - # game_layer.place_foundation(freeSpace[(i//5)+2], game_layer.game_state.available_residence_buildings[i//5].building_name) - - if (game_layer.game_state.turn == 0): - game_layer.place_foundation(freeSpace[2], game_layer.game_state.available_residence_buildings[0].building_name) - the_first_residence = state.residences[0] - if the_first_residence.build_progress < 100: - game_layer.build(freeSpace[2]) - if len(state.residences) == 1: - game_layer.place_foundation(freeSpace[3], game_layer.game_state.available_residence_buildings[5].building_name) - the_second_residence = state.residences[1] - if the_second_residence.build_progress < 100: - game_layer.build(freeSpace[3]) - if len(state.residences) == 2: - game_layer.place_foundation(freeSpace[5], game_layer.game_state.available_residence_buildings[1].building_name) - the_third_residence = state.residences[2] - if the_third_residence.build_progress < 100: - game_layer.build(freeSpace[5]) - if len(state.residences) == 3: - game_layer.place_foundation((4,4), game_layer.game_state.available_residence_buildings[4].building_name) - the_fourth_residence = state.residences[3] - if the_fourth_residence.build_progress < 100: - game_layer.build((4,4)) - - if len(state.residences) == 4: - game_layer.place_foundation((4,5), game_layer.game_state.available_residence_buildings[3].building_name) - the_fifth_residence = state.residences[4] - if the_fifth_residence.build_progress < 100: - game_layer.build((4,5)) - - if len(state.residences) == 5: - game_layer.place_foundation((4,6), game_layer.game_state.available_residence_buildings[4].building_name) - the_sixth_residence = state.residences[5] - if (the_sixth_residence.build_progress < 100) and game_layer.game_state.funds > 4000: - game_layer.build((4,6)) - - elif the_first_residence.health < 70: - game_layer.maintenance(freeSpace[2]) - elif the_second_residence.health < 70: - game_layer.maintenance(freeSpace[3]) - elif the_third_residence.health < 70: - game_layer.maintenance(freeSpace[5]) - elif the_fourth_residence.health < 70: - game_layer.maintenance((4,4)) - elif the_fifth_residence.health < 70: - game_layer.maintenance((4,5)) - elif the_sixth_residence.health < 70: - game_layer.maintenance((4,6)) - elif (the_second_residence.health > 70) and not len(state.utilities) > 0: - game_layer.place_foundation(freeSpace[4], game_layer.game_state.available_utility_buildings[2].building_name) - elif (state.utilities[0].build_progress < 100): - game_layer.build(freeSpace[4]) - - - #elif (game_layer.game_state.turn > 35) and not len(state.utilities) > 1: - # game_layer.place_foundation((4,6), game_layer.game_state.available_utility_buildings[1].building_name) - #elif (state.utilities[1].build_progress < 100): - # game_layer.build((4,6)) - - elif (game_layer.game_state.turn % rounds_between_energy == 0): - adjustEnergy(the_first_residence) - elif (game_layer.game_state.turn % rounds_between_energy == 1): - adjustEnergy(the_second_residence) - elif (game_layer.game_state.turn % rounds_between_energy == 2): - adjustEnergy(the_third_residence) - elif (game_layer.game_state.turn % rounds_between_energy == 3): - adjustEnergy(the_fourth_residence) - elif (game_layer.game_state.turn % rounds_between_energy == 4): - adjustEnergy(the_fifth_residence) - elif (game_layer.game_state.turn % rounds_between_energy == 5): - adjustEnergy(the_sixth_residence) - else: - # messages and errors for console log - game_layer.wait() - for message in game_layer.game_state.messages: - print(message) - for error in game_layer.game_state.errors: - print("Error: " + error) def take_turn(): if not usePrebuiltStrategy: @@ -270,15 +182,11 @@ def adjustEnergy(currentBuilding): game_layer.wait() - - - def optimizeAvailableTiles(): #hitta #utilities antal bästa platser i mitten av smeten och sätt de först, sätt allt runt dem i ordning så närmast är längst fram i listan pass - def build(structure): print("Building " + structure) state = game_layer.game_state From 36521b7bf76352ec647db953d15d7170ccff6bf2 Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 16:43:52 +0200 Subject: [PATCH 06/20] flytta lite kod --- main.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/main.py b/main.py index 93e8bb2..cf40c9b 100644 --- a/main.py +++ b/main.py @@ -106,6 +106,17 @@ def take_turn(): for error in game_layer.game_state.errors: print("Error: " + error) +def develop_society(): + state = game_layer.game_state + if len(state.residences) < 5: + build("Apartments") + elif len(state.utilities) < 1: + build("WindTurbine") + elif state.funds > 25000 and len(game_layer.game_state.residences) < 11: + build("HighRise") + else: + game_layer.wait() + def something_needs_attention(): print("Checking for emergencies") global building_under_construction @@ -144,17 +155,6 @@ def something_needs_attention(): else: return False -def develop_society(): - state = game_layer.game_state - if len(state.residences) < 5: - build("Apartments") - elif len(state.utilities) < 1: - build("WindTurbine") - elif state.funds > 25000 and len(game_layer.game_state.residences) < 11: - build("HighRise") - else: - game_layer.wait() - def chartMap(): state = game_layer.game_state for x in range(len(state.map) - 1): From c2d40778f028414285cd316cc39465009c3eefaf Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 18:28:59 +0200 Subject: [PATCH 07/20] =?UTF-8?q?wrapper=20s=C3=A5=20man=20kan=20k=C3=B6ra?= =?UTF-8?q?=20m=C3=A5nga=20games=20i=20rad=20(ej=20paralaliserad)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- launcher.py | 7 +++++++ main.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 launcher.py diff --git a/launcher.py b/launcher.py new file mode 100644 index 0000000..c922d71 --- /dev/null +++ b/launcher.py @@ -0,0 +1,7 @@ +import main +number_of_launches = 6 +result_list = [] +for i in range(number_of_launches): + result_list.append(main.main()) +for result in result_list: + print("Game " + result[0] + " had a score of: " + str(result[1])) \ No newline at end of file diff --git a/main.py b/main.py index cf40c9b..b9b967b 100644 --- a/main.py +++ b/main.py @@ -48,7 +48,7 @@ def main(): exit() print("Done with game: " + game_layer.game_state.game_id) print("Final score was: " + str(game_layer.get_score()["finalScore"])) - + return (game_layer.game_state.game_id, game_layer.get_score()["finalScore"]) def take_turn(): if not usePrebuiltStrategy: From de2b5181e00648061580859cf33a438ce10a07c8 Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 18:29:35 +0200 Subject: [PATCH 08/20] =?UTF-8?q?hitta=20"average"=20tile=20och=20sortera?= =?UTF-8?q?=20tiles=20utifr=C3=A5n=20avst=C3=A5nd=20till=20average?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index b9b967b..6215229 100644 --- a/main.py +++ b/main.py @@ -184,8 +184,27 @@ def adjustEnergy(currentBuilding): def optimizeAvailableTiles(): #hitta #utilities antal bästa platser i mitten av smeten och sätt de först, sätt allt runt dem i ordning så närmast är längst fram i listan - pass - + state = game_layer.game_state + global average_x, average_y, score_list + average_x = 0 + average_y = 0 + score_list = [] + for tile in availableTiles: #calc average coords + average_x += tile[0] + average_y += tile[1] + average_x /= len(availableTiles) + average_y /= len(availableTiles) + print("Assign scores") + for tile in availableTiles: + tile_score = abs(tile[0] - average_x) + abs(tile[1] - average_y) + score_list.append((tile_score, tile)) + def sort_key(e): + return e[0] + print("Sorting tile list") + score_list.sort(key=sort_key) + for i in range(len(score_list)): + availableTiles[i] = score_list[i][1] + print("average x,y: " + str(average_x) + ", " + str(average_y)) def build(structure): print("Building " + structure) From 3f678f69d782112712637051c8ccb5927e3a1420 Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 19:33:37 +0200 Subject: [PATCH 09/20] refactor variables, move code and use "state" --- main.py | 95 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/main.py b/main.py index 6215229..d1633d1 100644 --- a/main.py +++ b/main.py @@ -9,49 +9,51 @@ import traceback api_key = "74e3998d-ed3d-4d46-9ea8-6aab2efd8ae3" # The different map names can be found on considition.com/rules map_name = "training1" # TODO: You map choice here. If left empty, the map "training1" will be selected. - game_layer = GameLayer(api_key) -state = game_layer.game_state -usePrebuiltStrategy = False -timeUntilRunEnds = 50 -rounds_between_energy = 5 +#settings +use_prebuilt_strategy = False +time_until_run_ends = 70 utilities = 3 -EMA_temp = None -building_under_construction = None -availableTiles = [] - def main(): - #game_layer.force_end_game() + global EMA_temp, rounds_between_energy, building_under_construction, availableTiles, state + #global vars + rounds_between_energy = 5 + EMA_temp = None + building_under_construction = None + availableTiles = [] + game_layer.new_game(map_name) print("Starting game: " + game_layer.game_state.game_id) game_layer.start_game() - # exit game after timeout + # start timeout timer start_time = time.time() + state = game_layer.game_state chartMap() - global EMA_temp - while game_layer.game_state.turn < game_layer.game_state.max_turns: + while state.turn < state.max_turns: + state = game_layer.game_state try: if EMA_temp is None: - EMA_temp = game_layer.game_state.current_temp + EMA_temp = state.current_temp ema_k_value = (2/(rounds_between_energy+1)) - EMA_temp = game_layer.game_state.current_temp * ema_k_value + EMA_temp*(1-ema_k_value) + EMA_temp = state.current_temp * ema_k_value + EMA_temp*(1-ema_k_value) take_turn() except: print(traceback.format_exc()) game_layer.end_game() exit() time_diff = time.time() - start_time - if time_diff > timeUntilRunEnds: + if time_diff > time_until_run_ends: game_layer.end_game() exit() - print("Done with game: " + game_layer.game_state.game_id) + print("Done with game: " + state.game_id) print("Final score was: " + str(game_layer.get_score()["finalScore"])) - return (game_layer.game_state.game_id, game_layer.get_score()["finalScore"]) + return (state.game_id, game_layer.get_score()["finalScore"]) def take_turn(): - if not usePrebuiltStrategy: + global state + if not use_prebuilt_strategy: # TODO Implement your artificial intelligence here. # TODO Take one action per turn until the game ends. # TODO The following is a short example of how to use the StarterKit @@ -60,16 +62,14 @@ def take_turn(): else: develop_society() # messages and errors for console log - for message in game_layer.game_state.messages: + for message in state.messages: print(message) - for error in game_layer.game_state.errors: + for error in state.errors: print("Error: " + error) - # pre-made test strategy - # which came with - # starter kit - if usePrebuiltStrategy: + # pre-made test strategy which came with starter kit + if use_prebuilt_strategy: state = game_layer.game_state if len(state.residences) < 1: for i in range(len(state.map)): @@ -107,46 +107,52 @@ def take_turn(): print("Error: " + error) def develop_society(): - state = game_layer.game_state - if len(state.residences) < 5: + global state + + #check if queue is full + if state.housing_queue > 10 + len(state.utilities) * 0.15: + queue_is_full = True + else: + queue_is_full = False + + if len(state.residences) < 2: build("Apartments") elif len(state.utilities) < 1: build("WindTurbine") - elif state.funds > 25000 and len(game_layer.game_state.residences) < 11: + elif state.funds > 30000 and len(state.residences) < 4: build("HighRise") + elif queue_is_full: #build if queue full and can afford housing + + build("Apartments") + return True else: game_layer.wait() def something_needs_attention(): - print("Checking for emergencies") - global building_under_construction - global edit_temp - global maintain - state = game_layer.game_state + global building_under_construction, edit_temp, maintain, state #check if temp needs adjusting edit_temp = (False, 0) for i in range(len(state.residences)): if (state.turn % rounds_between_energy == i) and not state.residences[i].build_progress < 100: edit_temp = (True, i) - #check if need for maintainance maintain = (False, 0) for i in range(len(state.residences)): if state.residences[i].health < 41+rounds_between_energy*game_layer.get_residence_blueprint(state.residences[i].building_name).decay_rate: maintain = (True, i) - if maintain[0]: + if maintain[0]: #check maintainance game_layer.maintenance((state.residences[maintain[1]].X, state.residences[maintain[1]].Y)) return True - elif edit_temp[0]: #adjust temp of building + elif edit_temp[0]: #adjust temp of buildings adjustEnergy(state.residences[edit_temp[1]]) return True elif building_under_construction is not None: #finish construction - if (len(game_layer.game_state.residences) >= building_under_construction[2]) and (game_layer.game_state.residences[building_under_construction[2]].build_progress < 100): + if (len(state.residences)-1 >= building_under_construction[2]) and (state.residences[building_under_construction[2]].build_progress < 100): game_layer.build((building_under_construction[0], building_under_construction[1])) return True - elif (len(game_layer.game_state.utilities)-1 >= building_under_construction[2]) and (game_layer.game_state.utilities[building_under_construction[2]].build_progress < 100): + elif (len(state.utilities)-1 >= building_under_construction[2]) and (state.utilities[building_under_construction[2]].build_progress < 100): game_layer.build((building_under_construction[0], building_under_construction[1])) return True else: @@ -156,7 +162,7 @@ def something_needs_attention(): return False def chartMap(): - state = game_layer.game_state + global state for x in range(len(state.map) - 1): for y in range(len(state.map) - 1): if state.map[x][y] == 0: @@ -164,10 +170,9 @@ def chartMap(): optimizeAvailableTiles() def adjustEnergy(currentBuilding): - global rounds_between_energy - global EMA_temp + global rounds_between_energy, EMA_temp, state blueprint = game_layer.get_residence_blueprint(currentBuilding.building_name) - outDoorTemp = game_layer.game_state.current_temp * 2 - EMA_temp + outDoorTemp = state.current_temp * 2 - EMA_temp temp_acceleration = (2*(21 - currentBuilding.temperature)/(rounds_between_energy)) @@ -183,8 +188,6 @@ def adjustEnergy(currentBuilding): def optimizeAvailableTiles(): - #hitta #utilities antal bästa platser i mitten av smeten och sätt de först, sätt allt runt dem i ordning så närmast är längst fram i listan - state = game_layer.game_state global average_x, average_y, score_list average_x = 0 average_y = 0 @@ -208,9 +211,7 @@ def optimizeAvailableTiles(): def build(structure): print("Building " + structure) - state = game_layer.game_state - global building_under_construction - global rounds_between_energy + global building_under_construction, rounds_between_energy, state for i in range(len(availableTiles)): if isinstance(availableTiles[i], tuple): game_layer.place_foundation(availableTiles[i], structure) From a9ce9a96780b169e72b98c06fed512be213a139f Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 19:54:12 +0200 Subject: [PATCH 10/20] update construction status faster --- main.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index d1633d1..1985ce9 100644 --- a/main.py +++ b/main.py @@ -151,9 +151,13 @@ def something_needs_attention(): elif building_under_construction is not None: #finish construction if (len(state.residences)-1 >= building_under_construction[2]) and (state.residences[building_under_construction[2]].build_progress < 100): game_layer.build((building_under_construction[0], building_under_construction[1])) + if not state.residences[building_under_construction[2]].build_progress < 100: + building_under_construction = None return True elif (len(state.utilities)-1 >= building_under_construction[2]) and (state.utilities[building_under_construction[2]].build_progress < 100): game_layer.build((building_under_construction[0], building_under_construction[1])) + if not state.residences[building_under_construction[2]].build_progress < 100: + building_under_construction = None return True else: building_under_construction = None @@ -210,8 +214,8 @@ def optimizeAvailableTiles(): print("average x,y: " + str(average_x) + ", " + str(average_y)) def build(structure): - print("Building " + structure) global building_under_construction, rounds_between_energy, state + print("Building " + structure) for i in range(len(availableTiles)): if isinstance(availableTiles[i], tuple): game_layer.place_foundation(availableTiles[i], structure) From 876036fbe97f35c524ed002fbde6130aec00db5c Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 20:54:41 +0200 Subject: [PATCH 11/20] time out building new residences --- main.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/main.py b/main.py index 1985ce9..44d4881 100644 --- a/main.py +++ b/main.py @@ -17,12 +17,13 @@ utilities = 3 def main(): - global EMA_temp, rounds_between_energy, building_under_construction, availableTiles, state + global EMA_temp, rounds_between_energy, building_under_construction, availableTiles, state, queue_timeout #global vars rounds_between_energy = 5 EMA_temp = None building_under_construction = None availableTiles = [] + queue_timeout = 0 game_layer.new_game(map_name) print("Starting game: " + game_layer.game_state.game_id) @@ -107,13 +108,22 @@ def take_turn(): print("Error: " + error) def develop_society(): - global state + global state, queue_timeout #check if queue is full - if state.housing_queue > 10 + len(state.utilities) * 0.15: + if (state.housing_queue > 10 + len(state.utilities) * 0.15) and queue_timeout >= 5: queue_is_full = True + queue_timeout = 0 else: queue_is_full = False + queue_timeout += 1 + + build_residence_score = 0 + upgrade_residence_score = 0 + build_utility_score = 0 + build_upgrade_score = 0 + + decision_engine = None if len(state.residences) < 2: build("Apartments") @@ -122,9 +132,11 @@ def develop_society(): elif state.funds > 30000 and len(state.residences) < 4: build("HighRise") elif queue_is_full: #build if queue full and can afford housing - - build("Apartments") - return True + build("ModernApartments") + elif build_upgrade_score: + #if state.available_upgrades[0].name not in the_only_residence.effects: + # game_layer.buy_upgrade((the_only_residence.X, the_only_residence.Y), state.available_upgrades[0].name) + pass else: game_layer.wait() From 3b55e5a597813faad5d08f1f939f999fc65899cf Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 21:21:25 +0200 Subject: [PATCH 12/20] refactor available tiles --- main.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/main.py b/main.py index 44d4881..cfcae18 100644 --- a/main.py +++ b/main.py @@ -17,12 +17,12 @@ utilities = 3 def main(): - global EMA_temp, rounds_between_energy, building_under_construction, availableTiles, state, queue_timeout + global EMA_temp, rounds_between_energy, building_under_construction, available_tiles, state, queue_timeout #global vars rounds_between_energy = 5 EMA_temp = None building_under_construction = None - availableTiles = [] + available_tiles = [] queue_timeout = 0 game_layer.new_game(map_name) @@ -108,7 +108,7 @@ def take_turn(): print("Error: " + error) def develop_society(): - global state, queue_timeout + global state, queue_timeout, available_tiles #check if queue is full if (state.housing_queue > 10 + len(state.utilities) * 0.15) and queue_timeout >= 5: @@ -182,8 +182,8 @@ def chartMap(): for x in range(len(state.map) - 1): for y in range(len(state.map) - 1): if state.map[x][y] == 0: - availableTiles.append((x, y)) - optimizeAvailableTiles() + available_tiles.append((x, y)) + optimize_available_tiles() def adjustEnergy(currentBuilding): global rounds_between_energy, EMA_temp, state @@ -203,18 +203,18 @@ def adjustEnergy(currentBuilding): game_layer.wait() -def optimizeAvailableTiles(): +def optimize_available_tiles(): global average_x, average_y, score_list average_x = 0 average_y = 0 score_list = [] - for tile in availableTiles: #calc average coords + for tile in available_tiles: #calc average coords average_x += tile[0] average_y += tile[1] - average_x /= len(availableTiles) - average_y /= len(availableTiles) + average_x /= len(available_tiles) + average_y /= len(available_tiles) print("Assign scores") - for tile in availableTiles: + for tile in available_tiles: tile_score = abs(tile[0] - average_x) + abs(tile[1] - average_y) score_list.append((tile_score, tile)) def sort_key(e): @@ -222,22 +222,22 @@ def optimizeAvailableTiles(): print("Sorting tile list") score_list.sort(key=sort_key) for i in range(len(score_list)): - availableTiles[i] = score_list[i][1] + available_tiles[i] = score_list[i][1] print("average x,y: " + str(average_x) + ", " + str(average_y)) def build(structure): global building_under_construction, rounds_between_energy, state print("Building " + structure) - for i in range(len(availableTiles)): - if isinstance(availableTiles[i], tuple): - game_layer.place_foundation(availableTiles[i], structure) + for i in range(len(available_tiles)): + if isinstance(available_tiles[i], tuple): + game_layer.place_foundation(available_tiles[i], structure) for building in state.available_residence_buildings: if structure in building.building_name: for j in range(len(state.residences)): building = state.residences[j] coords_to_check = (building.X, building.Y) - if coords_to_check == availableTiles[i]: - availableTiles[i] = building + if coords_to_check == available_tiles[i]: + available_tiles[i] = building building_under_construction = (building.X, building.Y, j) rounds_between_energy = len(state.residences)+2 return True @@ -246,8 +246,8 @@ def build(structure): for j in range(len(state.utilities)): building = state.utilities[j] coords_to_check = (building.X, building.Y) - if coords_to_check == availableTiles[i]: - availableTiles[i] = building + if coords_to_check == available_tiles[i]: + available_tiles[i] = building building_under_construction = (building.X, building.Y, j) rounds_between_energy = len(state.residences)+2 return True From a830dd5d8137c9c408394d7d289cc441cffee998 Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 21:35:14 +0200 Subject: [PATCH 13/20] refactor and clear up code (whitespaces etc) --- main.py | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/main.py b/main.py index cfcae18..8efcbc8 100644 --- a/main.py +++ b/main.py @@ -10,7 +10,7 @@ api_key = "74e3998d-ed3d-4d46-9ea8-6aab2efd8ae3" # The different map names can be found on considition.com/rules map_name = "training1" # TODO: You map choice here. If left empty, the map "training1" will be selected. game_layer = GameLayer(api_key) -#settings +# settings use_prebuilt_strategy = False time_until_run_ends = 70 utilities = 3 @@ -18,7 +18,7 @@ utilities = 3 def main(): global EMA_temp, rounds_between_energy, building_under_construction, available_tiles, state, queue_timeout - #global vars + # global vars rounds_between_energy = 5 EMA_temp = None building_under_construction = None @@ -31,7 +31,7 @@ def main(): # start timeout timer start_time = time.time() state = game_layer.game_state - chartMap() + chart_map() while state.turn < state.max_turns: state = game_layer.game_state try: @@ -40,7 +40,7 @@ def main(): ema_k_value = (2/(rounds_between_energy+1)) EMA_temp = state.current_temp * ema_k_value + EMA_temp*(1-ema_k_value) take_turn() - except: + except Exception: print(traceback.format_exc()) game_layer.end_game() exit() @@ -52,6 +52,7 @@ def main(): print("Final score was: " + str(game_layer.get_score()["finalScore"])) return (state.game_id, game_layer.get_score()["finalScore"]) + def take_turn(): global state if not use_prebuilt_strategy: @@ -68,7 +69,6 @@ def take_turn(): for error in state.errors: print("Error: " + error) - # pre-made test strategy which came with starter kit if use_prebuilt_strategy: state = game_layer.game_state @@ -107,10 +107,11 @@ def take_turn(): for error in game_layer.game_state.errors: print("Error: " + error) + def develop_society(): global state, queue_timeout, available_tiles - #check if queue is full + # check if queue is full if (state.housing_queue > 10 + len(state.utilities) * 0.15) and queue_timeout >= 5: queue_is_full = True queue_timeout = 0 @@ -131,33 +132,34 @@ def develop_society(): build("WindTurbine") elif state.funds > 30000 and len(state.residences) < 4: build("HighRise") - elif queue_is_full: #build if queue full and can afford housing + elif queue_is_full: # build if queue full and can afford housing build("ModernApartments") elif build_upgrade_score: - #if state.available_upgrades[0].name not in the_only_residence.effects: + # if state.available_upgrades[0].name not in the_only_residence.effects: # game_layer.buy_upgrade((the_only_residence.X, the_only_residence.Y), state.available_upgrades[0].name) pass else: game_layer.wait() + def something_needs_attention(): global building_under_construction, edit_temp, maintain, state - #check if temp needs adjusting + # check if temp needs adjusting edit_temp = (False, 0) for i in range(len(state.residences)): if (state.turn % rounds_between_energy == i) and not state.residences[i].build_progress < 100: edit_temp = (True, i) - #check if need for maintainance + # check if need for maintenance maintain = (False, 0) for i in range(len(state.residences)): if state.residences[i].health < 41+rounds_between_energy*game_layer.get_residence_blueprint(state.residences[i].building_name).decay_rate: maintain = (True, i) - if maintain[0]: #check maintainance + if maintain[0]: # check maintenance game_layer.maintenance((state.residences[maintain[1]].X, state.residences[maintain[1]].Y)) return True - elif edit_temp[0]: #adjust temp of buildings + elif edit_temp[0]: # adjust temp of buildings adjustEnergy(state.residences[edit_temp[1]]) return True elif building_under_construction is not None: #finish construction @@ -177,7 +179,7 @@ def something_needs_attention(): else: return False -def chartMap(): +def chart_map(): global state for x in range(len(state.map) - 1): for y in range(len(state.map) - 1): @@ -185,19 +187,20 @@ def chartMap(): available_tiles.append((x, y)) optimize_available_tiles() -def adjustEnergy(currentBuilding): + +def adjust_energy(current_building): global rounds_between_energy, EMA_temp, state - blueprint = game_layer.get_residence_blueprint(currentBuilding.building_name) + blueprint = game_layer.get_residence_blueprint(current_building.building_name) outDoorTemp = state.current_temp * 2 - EMA_temp - temp_acceleration = (2*(21 - currentBuilding.temperature)/(rounds_between_energy)) + temp_acceleration = (2*(21 - current_building.temperature)/(rounds_between_energy)) - effectiveEnergyIn = ((temp_acceleration - 0.04 * currentBuilding.current_pop + (currentBuilding.temperature - outDoorTemp) * blueprint.emissivity) / 0.75) + blueprint.base_energy_need + effectiveEnergyIn = ((temp_acceleration - 0.04 * current_building.current_pop + (current_building.temperature - outDoorTemp) * blueprint.emissivity) / 0.75) + blueprint.base_energy_need if effectiveEnergyIn > blueprint.base_energy_need: - game_layer.adjust_energy_level((currentBuilding.X, currentBuilding.Y), effectiveEnergyIn) + game_layer.adjust_energy_level((current_building.X, current_building.Y), effectiveEnergyIn) elif effectiveEnergyIn < blueprint.base_energy_need: - game_layer.adjust_energy_level((currentBuilding.X, currentBuilding.Y), blueprint.base_energy_need + 0.01) + game_layer.adjust_energy_level((current_building.X, current_building.Y), blueprint.base_energy_need + 0.01) else: print("you did it!") game_layer.wait() @@ -208,7 +211,7 @@ def optimize_available_tiles(): average_x = 0 average_y = 0 score_list = [] - for tile in available_tiles: #calc average coords + for tile in available_tiles: # calc average coordinates average_x += tile[0] average_y += tile[1] average_x /= len(available_tiles) @@ -217,6 +220,7 @@ def optimize_available_tiles(): for tile in available_tiles: tile_score = abs(tile[0] - average_x) + abs(tile[1] - average_y) score_list.append((tile_score, tile)) + def sort_key(e): return e[0] print("Sorting tile list") @@ -225,6 +229,7 @@ def optimize_available_tiles(): available_tiles[i] = score_list[i][1] print("average x,y: " + str(average_x) + ", " + str(average_y)) + def build(structure): global building_under_construction, rounds_between_energy, state print("Building " + structure) From 638ebcfd721846ed78aebd7283417368bf5201f6 Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 21:35:34 +0200 Subject: [PATCH 14/20] change energy return (wasted wait()) --- main.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index 8efcbc8..c8af3d4 100644 --- a/main.py +++ b/main.py @@ -160,9 +160,8 @@ def something_needs_attention(): game_layer.maintenance((state.residences[maintain[1]].X, state.residences[maintain[1]].Y)) return True elif edit_temp[0]: # adjust temp of buildings - adjustEnergy(state.residences[edit_temp[1]]) - return True - elif building_under_construction is not None: #finish construction + return adjust_energy(state.residences[edit_temp[1]]) + elif building_under_construction is not None: # finish construction if (len(state.residences)-1 >= building_under_construction[2]) and (state.residences[building_under_construction[2]].build_progress < 100): game_layer.build((building_under_construction[0], building_under_construction[1])) if not state.residences[building_under_construction[2]].build_progress < 100: @@ -199,11 +198,12 @@ def adjust_energy(current_building): if effectiveEnergyIn > blueprint.base_energy_need: game_layer.adjust_energy_level((current_building.X, current_building.Y), effectiveEnergyIn) + return True elif effectiveEnergyIn < blueprint.base_energy_need: game_layer.adjust_energy_level((current_building.X, current_building.Y), blueprint.base_energy_need + 0.01) + return True else: - print("you did it!") - game_layer.wait() + return False def optimize_available_tiles(): From 9713be3eaf8aa6b0fe52af1b203de83474ec59cb Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Mon, 5 Oct 2020 22:58:09 +0200 Subject: [PATCH 15/20] =?UTF-8?q?kommentera=20trash=20metoden,=20optimizat?= =?UTF-8?q?ions,=20jobb=20p=C3=A5=20decision=20engine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 140 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 69 insertions(+), 71 deletions(-) diff --git a/main.py b/main.py index c8af3d4..40602b1 100644 --- a/main.py +++ b/main.py @@ -11,7 +11,6 @@ api_key = "74e3998d-ed3d-4d46-9ea8-6aab2efd8ae3" map_name = "training1" # TODO: You map choice here. If left empty, the map "training1" will be selected. game_layer = GameLayer(api_key) # settings -use_prebuilt_strategy = False time_until_run_ends = 70 utilities = 3 @@ -23,7 +22,7 @@ def main(): EMA_temp = None building_under_construction = None available_tiles = [] - queue_timeout = 0 + queue_timeout = 1 game_layer.new_game(map_name) print("Starting game: " + game_layer.game_state.game_id) @@ -55,106 +54,105 @@ def main(): def take_turn(): global state - if not use_prebuilt_strategy: - # TODO Implement your artificial intelligence here. - # TODO Take one action per turn until the game ends. - # TODO The following is a short example of how to use the StarterKit - if something_needs_attention(): - pass - else: - develop_society() - # messages and errors for console log - for message in state.messages: - print(message) - for error in state.errors: - print("Error: " + error) + # TODO Implement your artificial intelligence here. + # TODO Take one action per turn until the game ends. + # TODO The following is a short example of how to use the StarterKit + if something_needs_attention(): + pass + else: + develop_society() + # messages and errors for console log + for message in state.messages: + print(message) + for error in state.errors: + print("Error: " + error) # pre-made test strategy which came with starter kit - if use_prebuilt_strategy: - state = game_layer.game_state - if len(state.residences) < 1: - for i in range(len(state.map)): - for j in range(len(state.map)): - if state.map[i][j] == 0: - x = i - y = j - break - game_layer.place_foundation((x, y), game_layer.game_state.available_residence_buildings[0].building_name) + ''' + state = game_layer.game_state + if len(state.residences) < 1: + for i in range(len(state.map)): + for j in range(len(state.map)): + if state.map[i][j] == 0: + x = i + y = j + break + game_layer.place_foundation((x, y), game_layer.game_state.available_residence_buildings[0].building_name) + else: + the_only_residence = state.residences[0] + if the_only_residence.build_progress < 100: + game_layer.build((the_only_residence.X, the_only_residence.Y)) + elif the_only_residence.health < 50: + game_layer.maintenance((the_only_residence.X, the_only_residence.Y)) + elif the_only_residence.temperature < 18: + blueprint = game_layer.get_residence_blueprint(the_only_residence.building_name) + energy = blueprint.base_energy_need + 0.5 \ + + (the_only_residence.temperature - state.current_temp) * blueprint.emissivity / 1 \ + - the_only_residence.current_pop * 0.04 + game_layer.adjust_energy_level((the_only_residence.X, the_only_residence.Y), energy) + elif the_only_residence.temperature > 24: + blueprint = game_layer.get_residence_blueprint(the_only_residence.building_name) + energy = blueprint.base_energy_need - 0.5 \ + + (the_only_residence.temperature - state.current_temp) * blueprint.emissivity / 1 \ + - the_only_residence.current_pop * 0.04 + game_layer.adjust_energy_level((the_only_residence.X, the_only_residence.Y), energy) + elif state.available_upgrades[0].name not in the_only_residence.effects: + game_layer.buy_upgrade((the_only_residence.X, the_only_residence.Y), state.available_upgrades[0].name) else: - the_only_residence = state.residences[0] - if the_only_residence.build_progress < 100: - game_layer.build((the_only_residence.X, the_only_residence.Y)) - elif the_only_residence.health < 50: - game_layer.maintenance((the_only_residence.X, the_only_residence.Y)) - elif the_only_residence.temperature < 18: - blueprint = game_layer.get_residence_blueprint(the_only_residence.building_name) - energy = blueprint.base_energy_need + 0.5 \ - + (the_only_residence.temperature - state.current_temp) * blueprint.emissivity / 1 \ - - the_only_residence.current_pop * 0.04 - game_layer.adjust_energy_level((the_only_residence.X, the_only_residence.Y), energy) - elif the_only_residence.temperature > 24: - blueprint = game_layer.get_residence_blueprint(the_only_residence.building_name) - energy = blueprint.base_energy_need - 0.5 \ - + (the_only_residence.temperature - state.current_temp) * blueprint.emissivity / 1 \ - - the_only_residence.current_pop * 0.04 - game_layer.adjust_energy_level((the_only_residence.X, the_only_residence.Y), energy) - elif state.available_upgrades[0].name not in the_only_residence.effects: - game_layer.buy_upgrade((the_only_residence.X, the_only_residence.Y), state.available_upgrades[0].name) - else: - game_layer.wait() - for message in game_layer.game_state.messages: - print(message) - for error in game_layer.game_state.errors: - print("Error: " + error) + game_layer.wait() + for message in game_layer.game_state.messages: + print(message) + for error in game_layer.game_state.errors: + print("Error: " + error) + ''' def develop_society(): global state, queue_timeout, available_tiles + if queue_timeout > 1: + queue_timeout -= 1 - # check if queue is full - if (state.housing_queue > 10 + len(state.utilities) * 0.15) and queue_timeout >= 5: - queue_is_full = True - queue_timeout = 0 - else: - queue_is_full = False - queue_timeout += 1 - build_residence_score = 0 + # priority scores, 1 = very urgent, 0 = not urgent at all + build_residence_score = state.housing_queue / (15 * queue_timeout) upgrade_residence_score = 0 build_utility_score = 0 - build_upgrade_score = 0 + build_upgrade_score = 1 - state.turn/700 - decision_engine = None + actions = { + 'build_residence': build_residence_score, + 'upgrade_residence': upgrade_residence_score, + 'build_utility': build_utility_score, + 'build_upgrade': build_upgrade_score + } + decision = str(max(actions, key=actions.get)) if len(state.residences) < 2: build("Apartments") - elif len(state.utilities) < 1: + elif decision == "build_utility": build("WindTurbine") - elif state.funds > 30000 and len(state.residences) < 4: - build("HighRise") - elif queue_is_full: # build if queue full and can afford housing + elif decision == "build_residence": # build if queue full and can afford housing build("ModernApartments") - elif build_upgrade_score: + elif decision == "build_upgrade": # if state.available_upgrades[0].name not in the_only_residence.effects: # game_layer.buy_upgrade((the_only_residence.X, the_only_residence.Y), state.available_upgrades[0].name) - pass + game_layer.wait() else: game_layer.wait() def something_needs_attention(): - global building_under_construction, edit_temp, maintain, state + global building_under_construction, edit_temp, maintain, state, rounds_between_energy # check if temp needs adjusting edit_temp = (False, 0) - for i in range(len(state.residences)): - if (state.turn % rounds_between_energy == i) and not state.residences[i].build_progress < 100: - edit_temp = (True, i) # check if need for maintenance maintain = (False, 0) for i in range(len(state.residences)): - if state.residences[i].health < 41+rounds_between_energy*game_layer.get_residence_blueprint(state.residences[i].building_name).decay_rate: + if state.residences[i].health < 35+rounds_between_energy*game_layer.get_residence_blueprint(state.residences[i].building_name).decay_rate: maintain = (True, i) + if (state.turn % rounds_between_energy == i) and not state.residences[i].build_progress < 100: + edit_temp = (True, i) if maintain[0]: # check maintenance game_layer.maintenance((state.residences[maintain[1]].X, state.residences[maintain[1]].Y)) From db7c1c05be73f905adfbbfd8e530ab7c2fb3dc5c Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Tue, 6 Oct 2020 00:18:36 +0200 Subject: [PATCH 16/20] brain mechanics --- main.py | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/main.py b/main.py index 40602b1..c4c3d2c 100644 --- a/main.py +++ b/main.py @@ -59,8 +59,11 @@ def take_turn(): # TODO The following is a short example of how to use the StarterKit if something_needs_attention(): pass + elif develop_society(): + pass else: - develop_society() + game_layer.wait() + # messages and errors for console log for message in state.messages: print(message) @@ -108,16 +111,17 @@ def take_turn(): def develop_society(): - global state, queue_timeout, available_tiles + global state, queue_timeout, available_tiles, utilities if queue_timeout > 1: queue_timeout -= 1 # priority scores, 1 = very urgent, 0 = not urgent at all - build_residence_score = state.housing_queue / (15 * queue_timeout) + # queue modifier * funds modifier * existing houses modifier + build_residence_score = (state.housing_queue / (15 * queue_timeout)) * (1 - 7500/state.funds) * (1 - len(state.residences) / (len(available_tiles)-utilities)) upgrade_residence_score = 0 - build_utility_score = 0 - build_upgrade_score = 1 - state.turn/700 + build_utility_score = (len(state.residences) / (len(available_tiles)-utilities)) * (1 - len(state.utilities) / utilities) + build_upgrade_score = (1 - state.turn/700) * (2 - 15000/state.funds) actions = { 'build_residence': build_residence_score, @@ -127,18 +131,19 @@ def develop_society(): } decision = str(max(actions, key=actions.get)) - if len(state.residences) < 2: - build("Apartments") + if len(state.residences) < 1: + return build("Apartments") elif decision == "build_utility": - build("WindTurbine") + return build("WindTurbine") elif decision == "build_residence": # build if queue full and can afford housing - build("ModernApartments") + return build("ModernApartments") elif decision == "build_upgrade": - # if state.available_upgrades[0].name not in the_only_residence.effects: - # game_layer.buy_upgrade((the_only_residence.X, the_only_residence.Y), state.available_upgrades[0].name) - game_layer.wait() - else: - game_layer.wait() + for i in range(5): + for residence in state.residences: + if state.available_upgrades[i].name not in residence.effects: + game_layer.buy_upgrade((residence.X, residence.Y), state.available_upgrades[i].name) + return True + def something_needs_attention(): @@ -214,14 +219,12 @@ def optimize_available_tiles(): average_y += tile[1] average_x /= len(available_tiles) average_y /= len(available_tiles) - print("Assign scores") for tile in available_tiles: tile_score = abs(tile[0] - average_x) + abs(tile[1] - average_y) score_list.append((tile_score, tile)) def sort_key(e): return e[0] - print("Sorting tile list") score_list.sort(key=sort_key) for i in range(len(score_list)): available_tiles[i] = score_list[i][1] @@ -230,7 +233,7 @@ def optimize_available_tiles(): def build(structure): global building_under_construction, rounds_between_energy, state - print("Building " + structure) + # print("Building " + structure) for i in range(len(available_tiles)): if isinstance(available_tiles[i], tuple): game_layer.place_foundation(available_tiles[i], structure) From 8309d2938c1ba2d8ad4d4b22e930588ab18e2858 Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Tue, 6 Oct 2020 01:49:09 +0200 Subject: [PATCH 17/20] =?UTF-8?q?adjust=20energy=20ta=20h=C3=A4nsyn=20till?= =?UTF-8?q?=20upgrades?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index c4c3d2c..2e50fa4 100644 --- a/main.py +++ b/main.py @@ -193,17 +193,24 @@ def chart_map(): def adjust_energy(current_building): global rounds_between_energy, EMA_temp, state blueprint = game_layer.get_residence_blueprint(current_building.building_name) - outDoorTemp = state.current_temp * 2 - EMA_temp + base_energy = blueprint.base_energy_need + if "Charger" in current_building.effects: + base_energy += 1.8 + emissivity = blueprint.emissivity + if "Insulation" in current_building.effects: + emissivity *= 0.6 + + outDoorTemp = state.current_temp * 2 - EMA_temp temp_acceleration = (2*(21 - current_building.temperature)/(rounds_between_energy)) - effectiveEnergyIn = ((temp_acceleration - 0.04 * current_building.current_pop + (current_building.temperature - outDoorTemp) * blueprint.emissivity) / 0.75) + blueprint.base_energy_need + effectiveEnergyIn = ((temp_acceleration - 0.04 * current_building.current_pop + (current_building.temperature - outDoorTemp) * emissivity) / 0.75) + base_energy - if effectiveEnergyIn > blueprint.base_energy_need: + if effectiveEnergyIn > base_energy: game_layer.adjust_energy_level((current_building.X, current_building.Y), effectiveEnergyIn) return True - elif effectiveEnergyIn < blueprint.base_energy_need: - game_layer.adjust_energy_level((current_building.X, current_building.Y), blueprint.base_energy_need + 0.01) + elif effectiveEnergyIn < base_energy: + game_layer.adjust_energy_level((current_building.X, current_building.Y), base_energy + 0.01) return True else: return False From 2cda0a08b7f19c4b0a056ab8709b38f60b920e13 Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Tue, 6 Oct 2020 01:49:23 +0200 Subject: [PATCH 18/20] decision engine rework --- main.py | 61 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/main.py b/main.py index 2e50fa4..466938a 100644 --- a/main.py +++ b/main.py @@ -118,31 +118,48 @@ def develop_society(): # priority scores, 1 = very urgent, 0 = not urgent at all # queue modifier * funds modifier * existing houses modifier - build_residence_score = (state.housing_queue / (15 * queue_timeout)) * (1 - 7500/state.funds) * (1 - len(state.residences) / (len(available_tiles)-utilities)) + build_residence_score = (state.housing_queue / (15 * queue_timeout)) * (1 - (7500 / state.funds)) * (1 - (len(state.residences) / (len(available_tiles)-utilities))) upgrade_residence_score = 0 - build_utility_score = (len(state.residences) / (len(available_tiles)-utilities)) * (1 - len(state.utilities) / utilities) - build_upgrade_score = (1 - state.turn/700) * (2 - 15000/state.funds) - - actions = { - 'build_residence': build_residence_score, - 'upgrade_residence': upgrade_residence_score, - 'build_utility': build_utility_score, - 'build_upgrade': build_upgrade_score - } - decision = str(max(actions, key=actions.get)) + # existing houses modifier * funds modifier * existing utilities modifier + build_utility_score = (len(state.residences) / (len(available_tiles)-utilities)) * (1 - (16000 / state.funds)) * (1 - (len(state.utilities) / utilities)) + # turn modifier * funds modifier + build_upgrade_score = (1 - (state.turn / 700)) * (2 - (15000 / state.funds)) if len(state.residences) < 1: - return build("Apartments") - elif decision == "build_utility": - return build("WindTurbine") - elif decision == "build_residence": # build if queue full and can afford housing - return build("ModernApartments") - elif decision == "build_upgrade": - for i in range(5): - for residence in state.residences: - if state.available_upgrades[i].name not in residence.effects: - game_layer.buy_upgrade((residence.X, residence.Y), state.available_upgrades[i].name) - return True + build_residence_score = 100 + + decision = [ + ('build_residence', build_residence_score), + ('upgrade_residence', upgrade_residence_score), + ('build_utility', build_utility_score), + ('build_upgrade', build_upgrade_score) + ] + def sort_key(e): + return e[1] + decision.sort(reverse=True, key=sort_key) + print(decision) + + for i in range(4): + if decision[0][0] == "build_residence": # build housing + queue_timeout = 5 + #return build("ModernApartments") + if len(state.residences) < len(state.available_residence_buildings): + return build(state.available_residence_buildings[len(state.residences)].building_name) + + if decision[0][0] == "build_utility": # build utilities + return build("WindTurbine") + + if decision[0][0] == "upgrade_residence": # build utilities + pass + + if decision[0][0] == "build_upgrade": # build upgrades + for i in range(6): + for residence in state.residences: + if state.available_upgrades[i].name not in residence.effects: + game_layer.buy_upgrade((residence.X, residence.Y), state.available_upgrades[i].name) + return True + del decision[0] + return False From 9ae3b54c417ae06d5cc47cd93530503f8a01252b Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Tue, 6 Oct 2020 02:02:28 +0200 Subject: [PATCH 19/20] move function --- main.py | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/main.py b/main.py index 466938a..73a418c 100644 --- a/main.py +++ b/main.py @@ -142,10 +142,10 @@ def develop_society(): for i in range(4): if decision[0][0] == "build_residence": # build housing queue_timeout = 5 - #return build("ModernApartments") if len(state.residences) < len(state.available_residence_buildings): return build(state.available_residence_buildings[len(state.residences)].building_name) - + else: + calculate_residence_score() if decision[0][0] == "build_utility": # build utilities return build("WindTurbine") @@ -198,6 +198,7 @@ def something_needs_attention(): else: return False + def chart_map(): global state for x in range(len(state.map) - 1): @@ -207,6 +208,28 @@ def chart_map(): optimize_available_tiles() +def optimize_available_tiles(): + global average_x, average_y, score_list + average_x = 0 + average_y = 0 + score_list = [] + for tile in available_tiles: # calc average coordinates + average_x += tile[0] + average_y += tile[1] + average_x /= len(available_tiles) + average_y /= len(available_tiles) + for tile in available_tiles: + tile_score = abs(tile[0] - average_x) + abs(tile[1] - average_y) + score_list.append((tile_score, tile)) + + def sort_key(e): + return e[0] + score_list.sort(key=sort_key) + for i in range(len(score_list)): + available_tiles[i] = score_list[i][1] + print("average x,y: " + str(average_x) + ", " + str(average_y)) + + def adjust_energy(current_building): global rounds_between_energy, EMA_temp, state blueprint = game_layer.get_residence_blueprint(current_building.building_name) @@ -233,28 +256,6 @@ def adjust_energy(current_building): return False -def optimize_available_tiles(): - global average_x, average_y, score_list - average_x = 0 - average_y = 0 - score_list = [] - for tile in available_tiles: # calc average coordinates - average_x += tile[0] - average_y += tile[1] - average_x /= len(available_tiles) - average_y /= len(available_tiles) - for tile in available_tiles: - tile_score = abs(tile[0] - average_x) + abs(tile[1] - average_y) - score_list.append((tile_score, tile)) - - def sort_key(e): - return e[0] - score_list.sort(key=sort_key) - for i in range(len(score_list)): - available_tiles[i] = score_list[i][1] - print("average x,y: " + str(average_x) + ", " + str(average_y)) - - def build(structure): global building_under_construction, rounds_between_energy, state # print("Building " + structure) From 1bb5ba898d18118afd059ddfe6022ceed9e51d8a Mon Sep 17 00:00:00 2001 From: Thefeli73 Date: Tue, 6 Oct 2020 05:06:04 +0200 Subject: [PATCH 20/20] decision logic, income, best upgrade/residence functions --- main.py | 128 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 112 insertions(+), 16 deletions(-) diff --git a/main.py b/main.py index 73a418c..458d761 100644 --- a/main.py +++ b/main.py @@ -13,6 +13,7 @@ game_layer = GameLayer(api_key) # settings time_until_run_ends = 70 utilities = 3 +money_reserve_multiplier = 1.5 def main(): @@ -118,12 +119,12 @@ def develop_society(): # priority scores, 1 = very urgent, 0 = not urgent at all # queue modifier * funds modifier * existing houses modifier - build_residence_score = (state.housing_queue / (15 * queue_timeout)) * (1 - (7500 / state.funds)) * (1 - (len(state.residences) / (len(available_tiles)-utilities))) + build_residence_score = (state.housing_queue / (15 * queue_timeout)) * (1 - (7500 / (1 + state.funds))) * (1 - (len(state.residences) / (1 + len(available_tiles) - utilities))) upgrade_residence_score = 0 # existing houses modifier * funds modifier * existing utilities modifier - build_utility_score = (len(state.residences) / (len(available_tiles)-utilities)) * (1 - (16000 / state.funds)) * (1 - (len(state.utilities) / utilities)) + build_utility_score = (len(state.residences) / (1 + len(available_tiles)-utilities)) * (1 - (16000 / (1 + state.funds))) * (1 - (len(state.utilities) / utilities)) # turn modifier * funds modifier - build_upgrade_score = (1 - (state.turn / 700)) * (2 - (15000 / state.funds)) + build_upgrade_score = (1 - (state.turn / 700)) * (2 - (15000 / (1 + state.funds))) if len(state.residences) < 1: build_residence_score = 100 @@ -137,28 +138,35 @@ def develop_society(): def sort_key(e): return e[1] decision.sort(reverse=True, key=sort_key) - print(decision) for i in range(4): if decision[0][0] == "build_residence": # build housing queue_timeout = 5 - if len(state.residences) < len(state.available_residence_buildings): - return build(state.available_residence_buildings[len(state.residences)].building_name) - else: - calculate_residence_score() + #if len(state.residences) < len(state.available_residence_buildings): + # return build(state.available_residence_buildings[len(state.residences)].building_name) + #else: + cbr = calculate_best_residence() + if cbr: + return build(cbr[1]) if decision[0][0] == "build_utility": # build utilities - return build("WindTurbine") - + #return build("WindTurbine") + pass if decision[0][0] == "upgrade_residence": # build utilities pass - if decision[0][0] == "build_upgrade": # build upgrades - for i in range(6): - for residence in state.residences: - if state.available_upgrades[i].name not in residence.effects: - game_layer.buy_upgrade((residence.X, residence.Y), state.available_upgrades[i].name) - return True + for residence in state.residences: + if state.available_upgrades[0].name not in residence.effects and (money_reserve_multiplier*3500 < state.funds) and ((total_income() - 6) > 50): + game_layer.buy_upgrade((residence.X, residence.Y), state.available_upgrades[0].name) + return True + if state.available_upgrades[5].name not in residence.effects and (money_reserve_multiplier*1250 < state.funds): + game_layer.buy_upgrade((residence.X, residence.Y), state.available_upgrades[5].name) + return True + gbp = get_best_upgrade() + if gbp: + game_layer.buy_upgrade((gbp[2].X, gbp[2].Y), gbp[1]) + return True del decision[0] + return False @@ -199,6 +207,94 @@ def something_needs_attention(): return False +def total_income(): + global state + income = 0 + for residence in state.residences: + income += game_layer.get_residence_blueprint(residence.building_name).income_per_pop * residence.current_pop + return income + + +def get_best_upgrade(): + global state + + best_upgrade = [] + for residence in state.residences: + cbu = calculate_best_upgrade(residence) + if cbu is not False: + score = cbu[0] + upgrade = cbu[1] + best_upgrade.append((score, upgrade, residence)) + + def sort_key(e): + return e[0] + best_upgrade.sort(reverse=True, key=sort_key) + if not best_upgrade: + return False + return best_upgrade[0] + + +def calculate_best_upgrade(current_building): + global state + + rounds_left = 700 - state.turn + current_pop = current_building.current_pop + blueprint = game_layer.get_blueprint(current_building.building_name) + base_energy_need = blueprint.base_energy_need + best_upgrade = [] + for upgrade in state.available_upgrades: + effect = game_layer.get_effect(upgrade.effect) + if (upgrade.name not in current_building.effects) and ((total_income() + effect.building_income_increase) > 50) and (money_reserve_multiplier*upgrade.cost < state.funds): + average_outdoor_temp = (state.max_temp - state.min_temp)/2 + + average_heating_energy = (((21 - average_outdoor_temp) * blueprint.emissivity * effect.emissivity_multiplier) / 0.75) + old_average_heating_energy = (((21 - average_outdoor_temp) * blueprint.emissivity) / 0.75) + + lifetime_energy = (base_energy_need + effect.base_energy_mwh_increase + average_heating_energy - effect.mwh_production) * rounds_left + old_lifetime_energy = (base_energy_need + old_average_heating_energy) * rounds_left + + + upgrade_co2 = (effect.co2_per_pop_increase * 0.03) * current_pop * rounds_left + (0.1 * lifetime_energy / 1000) + old_co2 = 0.03 * current_pop * rounds_left + (0.1 * old_lifetime_energy / 1000) + co2 = upgrade_co2 - old_co2 + max_happiness = effect.max_happiness_increase * rounds_left + + score = max_happiness/10 - co2 + best_upgrade.append((score, upgrade.name)) + + def sort_key(e): + return e[0] + best_upgrade.sort(reverse=True, key=sort_key) + if not best_upgrade: + return False + return best_upgrade[0] + + +def calculate_best_residence(): + global state + + rounds_left = 700 - state.turn + best_residence = [] + for residence_blueprint in state.available_residence_buildings: + if state.turn >= residence_blueprint.release_tick and (money_reserve_multiplier*residence_blueprint.cost < state.funds): + average_outdoor_temp = (state.max_temp - state.min_temp)/2 + average_heating_energy = ((0 - 0.04 * residence_blueprint.max_pop + (21 - average_outdoor_temp) * residence_blueprint.emissivity) / 0.75) + lifetime_energy = (residence_blueprint.base_energy_need + average_heating_energy) * rounds_left + + co2 = 0.03 * residence_blueprint.max_pop * rounds_left + residence_blueprint.co2_cost + (0.1 * lifetime_energy / 1000) + max_happiness = residence_blueprint.max_happiness * rounds_left + + score = residence_blueprint.max_pop*15 + max_happiness/10 - co2 + best_residence.append((score, residence_blueprint.building_name)) + + def sort_key(e): + return e[0] + best_residence.sort(reverse=True, key=sort_key) + if not best_residence: + return False + return best_residence[0] + + def chart_map(): global state for x in range(len(state.map) - 1):