def update(self):
        # movement
        if self.current_path:

            if self.next_tile is None:
                self.current_path = None
                # message telling the entity that is has arrived
                message = dispatcher.Message(self,
                                             dispatcher.MSG.ArrivedAtGoal)
                self.fsm.handle_message(message)

            else:
                (x1, y1) = self.location
                (x2, y2) = self.next_tile
                dx, dy = x2 - x1, y2 - y1
                # get required movement threshold
                threshold = self.current_tile.movement_straight if (
                    dx * dy == 0) else self.current_tile.movement_diagonal
                # take movement factor into account
                self.move_progress += time.clock.delta * self.move_factor
                if self.move_progress >= threshold:
                    # reset progress
                    self.move_progress = 0
                    # move
                    self.move(dx, dy)
                    # update next tile
                    self.next_tile = self.current_path[self.next_tile]

        super().update()
 def production_spawn(self):
     self.owner.production_list.remove(self)
     # put explorer where worker stood
     self.location = self.worker_unit.location
     super().spawn()
     # remove worker
     self.owner.remove_entity(self.worker_unit)
     # notify owner
     message = dispatcher.Message(self, dispatcher.MSG.NewArtisanUnit)
     self.owner.fsm.handle_message(message)
 def production_spawn(self):
     self.owner.production_list.remove(self)
     # position to building
     self.location = self.origin_structure.location
     # spawn
     super().spawn()
     # notify owner
     message = dispatcher.Message(self, dispatcher.MSG.NewWorkerUnit)
     self.owner.fsm.handle_message(message)
     # free structure
     self.origin_structure.fsm.change_state(states.StateIdle())
 def production_spawn(self):
     self.owner.production_list.remove(self)
     # put explorer where worker stood
     self.location = self.worker_unit.location
     super().spawn()
     # remove worker
     self.owner.remove_entity(self.worker_unit)
     # notify owner
     message = dispatcher.Message(self, dispatcher.MSG.NewSoldierUnit)
     self.owner.fsm.handle_message(message)
     # move to spec. loc
     self.fsm.change_state(states.StateMove())
 def production_spawn(self):
     self.owner.production_list.remove(self)
     # put explorer where worker stood
     self.location = self.worker_unit.location
     super().spawn()
     # clear any fog
     self.gamemap.discover_fog_area(
         (self.location[0] - 1, self.location[1] - 1),
         (self.location[0] + 1, self.location[1] + 1))
     # remove worker
     self.owner.remove_entity(self.worker_unit)
     # notify owner
     message = dispatcher.Message(self, dispatcher.MSG.NewExplorerUnit)
     self.owner.fsm.handle_message(message)
    def on_message(self, entity, message):
        # Go where work is needed if not currently walking
        if message.msg == dispatcher.MSG.ArtisanNeeded and not self.finding_path:
            self.finding_path = True
            self.target_structure = message.sender
            find_path(entity, entity.location, message.sender.location,
                      get_path_callback)
            return True
        # has arrived to work -> notify structure
        if message.msg == dispatcher.MSG.ArrivedAtGoal:
            message = dispatcher.Message(entity, dispatcher.MSG.ArtisanArrived)
            self.target_structure.fsm.handle_message(message)
            return True

        return False
    def execute(self, entity):
        if self.time_since_last_update >= self.update_interval:
            free_artisans = []
            target_artisans = []
            target_artisan_count = 0
            # count number of target_artisans and free artisans
            for artisan in entity.owner.entities_where(lambda e: isinstance(
                    e, entities.UnitArtisan) and e.is_visible):
                if artisan.profession == entity.artisan_required:
                    target_artisan_count += 1
                    target_artisans.append(artisan)
                elif artisan.profession == entities.UnitArtisan.Profession.Free:
                    free_artisans.append(artisan)
            # check to see if any more target_artisans needs to be created (currently 1)
            if target_artisan_count < 1:
                # assign artisan if needed
                if free_artisans:
                    free_artisans[0].profession = entity.artisan_required
                    free_artisans[0].fsm.change_state(StateArtisan())
                # has no free artisans -> order one
                else:
                    entity.owner.prepend_goal(
                        ["Unit", "Artisan",
                         4])  # currently maximun needed artisans
                    # can be incremented each time a structure requiring an artisan is built

            # try and get an artisan to come
            for artisan in target_artisans:
                if artisan.fsm.is_in_state(StateArtisan):
                    message = dispatcher.Message(entity,
                                                 dispatcher.MSG.ArtisanNeeded)
                    artisan.fsm.handle_message(message)
                    break

            # reset timer
            self.time_since_last_update = 0
        self.time_since_last_update += time.delta_time