Skip to content

Commit 647c34a

Browse files
committed
GH-2: Added complete fisrt version of the computer turn algorithm.
1 parent c96cb5e commit 647c34a

File tree

2 files changed

+83
-47
lines changed

2 files changed

+83
-47
lines changed

constants.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
"o": [10, 100, 50],
7272
"c": [100, 50, 25], # default of settlement store (level 1)
7373
}
74-
MAP_WALLS = ["s", "l", "m", "o"] # used in path algorithms to distinguish where the player can move.
74+
MAP_WALLS = ["s", "w", "m", "o"] # used in path algorithms to distinguish where the player can move.
7575

7676

7777
UNIT_SPECS = {

project/game/model.py

+82-46
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# Ben-Ryder 2019
2-
2+
import math
33
import random
44
import paths
55
import constants
66

77
import project.game.calculations as calculations
8+
import project.game.shortest_path as shortest_path
89

910

1011
class Model:
@@ -329,59 +330,94 @@ class ComputerPlayer(Player):
329330
def __init__(self, model_link, save_data):
330331
super().__init__(model_link, save_data)
331332

332-
def take_go(self, ):
333-
self.model_link.get_current_player().start_turn()
333+
def take_go(self):
334+
self.start_turn()
334335

335-
self.handle_cities()
336336
self.handle_units()
337+
self.handle_cities()
337338

338-
self.model_link.get_current_player().end_turn()
339+
self.end_turn()
340+
341+
def handle_units(self):
342+
for unit in self.units:
343+
344+
# Conquer: conquer a city if possible.
345+
if self.model_link.check_conquer(unit):
346+
self.model_link.conquer(unit.position)
347+
else:
348+
# Movement: move into an enemy/unoccupied city, or move closer to one.
349+
all_moves = self.model_link.get_moves(unit)
350+
cities = []
351+
for position in all_moves:
352+
tile = self.model_link.world.get_tile(position)
353+
if tile.get_type() == "c" and tile.get_holder() != self.get_name():
354+
cities.append(position)
355+
356+
if len(cities) > 0: # can move into enemy/unoccupied city
357+
city_position = random.choice(cities)
358+
self.model_link.move_unit(city_position, unit)
359+
else:
360+
# Getting all enemy/unoccupied cities
361+
all_cities = []
362+
for row in self.model_link.world.tiles:
363+
for tile in row:
364+
if tile.get_type() == "c" and tile.get_holder() != self.get_name():
365+
all_cities.append(tile.get_position())
366+
367+
# Getting closest city to the current player
368+
nearest_city = None
369+
nearest_city_heuristic = None
370+
for city_position in all_cities:
371+
x_distance = abs(unit.position[0] - city_position[0])
372+
y_distance = abs(unit.position[1] - city_position[1])
373+
heuristic = round(math.sqrt(x_distance ** 2 + y_distance ** 2))
374+
375+
if nearest_city is None:
376+
nearest_city = city_position
377+
nearest_city_heuristic = heuristic
378+
else:
379+
if heuristic < nearest_city_heuristic:
380+
nearest_city = city_position
381+
nearest_city_heuristic = heuristic
382+
383+
# Getting shortest path to the city
384+
city_path = shortest_path.GridPath(self.model_link.world.get_format(),
385+
unit.position, nearest_city,
386+
constants.MAP_WALLS).get_path()
387+
# Moving first step of the path
388+
valid_city_path = [move for move in city_path if move in all_moves]
389+
390+
if len(valid_city_path) > 0:
391+
self.model_link.move_unit(valid_city_path[0], unit)
392+
elif len(all_moves) > 0:
393+
random_move = random.choice(all_moves)
394+
self.model_link.move_unit(random_move, unit)
395+
396+
# Attack: attack the weakest enemy unit in range.
397+
all_attacks = self.model_link.get_attacks(unit)
398+
if len(all_attacks) > 0:
399+
all_units = sorted(
400+
[self.model_link.get_unit(position) for position in all_attacks],
401+
key=lambda x: x.health)
402+
enemy_unit = all_units[0] # target the weakest enemy
403+
self.model_link.make_attack(unit, enemy_unit)
339404

340405
def handle_cities(self):
341-
current_player = self.model_link.get_current_player()
342-
for city_position in current_player.settlements:
343-
# Spawning Units
344-
affordable_units = [name for name, values in constants.UNIT_SPECS.items()
345-
if current_player.get_ap() - values["spawn_cost"] >= 0]
346-
unit_choice = random.choice(affordable_units)
406+
# Upgrading Cities
407+
for city_position in self.settlements:
408+
city = self.model_link.world.get_tile(city_position)
409+
if city.can_upgrade():
410+
city.add_sub_level()
347411

412+
# Spawning Random Units
413+
for city_position in self.settlements:
348414
city = self.model_link.world.get_tile(city_position)
349-
self.model_link.try_spawn(unit_choice, city.get_position())
350415

351-
def handle_units(self):
352-
current_player = self.model_link.get_current_player()
353-
for unit in current_player.units:
354-
if False: # in city conquer it
355-
pass
356-
else:
357-
# breadth_search = breadth_first.BreadthSearch(model.world.get_format())
358-
#
359-
# nearest_city = breadth_search.get_nearest(unit.position, "c")
360-
# path = shortest_path.GridPath(
361-
# model.world.get_format(),
362-
# unit.position, nearest_city,
363-
# walls=MAP_WALLS
364-
# ).get_path()
365-
# print(path)
366-
367-
# See if unit can take a city
368-
if self.model_link.check_conquer(unit):
369-
self.model_link.conquer(unit.position)
370-
else:
371-
# Make Random Move
372-
all_moves = self.model_link.get_moves(unit)
373-
if len(all_moves) > 0:
374-
move = random.choice(all_moves)
375-
self.model_link.move_unit(move, unit)
376-
377-
# Make Random Attack (if possible)
378-
all_attacks = self.model_link.get_attacks(unit)
379-
if len(all_attacks) > 0:
380-
all_units = sorted(
381-
[self.model_link.get_unit(position) for position in all_attacks],
382-
key=lambda x: x.health)
383-
enemy_unit = all_units[0] # target the weakest enemy
384-
self.model_link.make_attack(unit, enemy_unit)
416+
affordable_units = [name for name, values in constants.UNIT_SPECS.items()
417+
if self.get_ap() - values["spawn_cost"] >= 0]
418+
if len(affordable_units) > 0:
419+
unit_choice = random.choice(affordable_units)
420+
self.model_link.try_spawn(unit_choice, city.get_position())
385421

386422

387423
class Tile:

0 commit comments

Comments
 (0)