Esempio n. 1
0
    def apply_state(self, state, remaining_ticks=None):
        """Takes actions to set collector to a state. Useful after loading.
		@param state: EnumValue from states
		@param remaining_ticks: ticks after which current state is finished
		"""
        if state == self.states.idle:
            # we do nothing, so schedule a new search for a job
            Scheduler().add_new_object(self.search_job, self, remaining_ticks)
        elif state == self.states.moving_to_target:
            # we are on the way to target, so save the job
            self.setup_new_job()
            # and notify us, when we're at target
            self.add_move_callback(self.begin_working)
            self.add_blocked_callback(self.handle_path_to_job_blocked)
            self.show()
        elif state == self.states.working:
            # we are at the target and work
            # register the new job
            self.setup_new_job()
            # job finishes in remaining_ticks ticks
            Scheduler().add_new_object(self.finish_working, self,
                                       remaining_ticks)
Esempio n. 2
0
    def test_sell(self):
        self.inventory.alter(1, 1)
        self.assertFalse(self.tradepost.sell(1, 1, 1, 100))
        self.tradepost.set_slot(0, 1, True, 0)  # sell until 0
        self.assertTrue(self.tradepost.sell(1, 1, 1, 100))
        self.assertEqual(self.tradepost.sell_income, 1)

        Scheduler().cur_tick += 1

        # ran out of res
        self.assertFalse(self.tradepost.sell(1, 1, 1, 100))

        Scheduler().cur_tick += 1

        self.inventory.alter(1, 1)
        self.assertTrue(self.tradepost.sell(1, 1, 1, 100))

        self.tradepost.clear_slot(0, True)
        # not selling any more
        self.assertFalse(self.tradepost.sell(1, 1, 1, 100))
        self.assertEqual(self.tradepost.sell_income, 2)
        self.assertEqual(self.tradepost.total_earnings, 2)
Esempio n. 3
0
 def load_ship_states(self, db):
     # load ships one by one from db (ship instances themselves are loaded already, but
     # we have to use them here)
     for ship_id, state_id, remaining_ticks in \
       db("SELECT rowid, state, remaining_ticks FROM pirate_ships"):
         state = self.shipStates[state_id]
         ship = WorldObject.get_object_by_id(ship_id)
         self.ships[ship] = state
         assert remaining_ticks is not None
         Scheduler().add_new_object(Callback(self.lookout, ship), self,
                                    remaining_ticks, -1, 8)
         ship.add_move_callback(Callback(self.ship_idle, ship))
         self.calculate_visibility_points(ship)
Esempio n. 4
0
	def _load(self, db, worldid):
		super(Production, self).load(db, worldid)

		db_data = db.get_production_row(worldid)
		self.__init(WorldObject.get_object_by_id(db_data[1]).inventory, db_data[2], \
								PRODUCTION.STATES[db_data[0]], None if db_data[4] is None else PRODUCTION.STATES[db_data[4]])
		if self._state == PRODUCTION.STATES.paused:
			self._pause_remaining_ticks = db_data[3]
		elif self._state == PRODUCTION.STATES.producing:
			Scheduler().add_new_object(self._finished_producing, self, db_data[3])
		elif self._state == PRODUCTION.STATES.waiting_for_res or \
		     self._state == PRODUCTION.STATES.inventory_full:
			self.inventory.add_change_listener(self._check_inventory)
Esempio n. 5
0
	def save(self, db):
		remaining_ticks = None
		if self._state == PRODUCTION.STATES.paused:
			remaining_ticks = self._pause_remaining_ticks
		elif self._state == PRODUCTION.STATES.producing:
			remaining_ticks = Scheduler().get_remaining_ticks(self, self._finished_producing)
		# use a number > 0 for ticks
		if remaining_ticks < 1:
			remaining_ticks = 1
		db('INSERT INTO production(rowid, state, prod_line_id, remaining_ticks, \
		_pause_old_state) VALUES(?, ?, ?, ?, ?)', self.worldid, self._state.index, \
												self._prod_line.id, remaining_ticks, \
												None if self._pause_old_state is None else self._pause_old_state.index)
Esempio n. 6
0
    def _ship_found_signal_fire(self, ship):
        signal_fire = self._check_for_signal_fire_in_ship_range(ship)
        self.log.debug("Trader %s ship %s found signal fire %s", self.worldid,
                       ship.worldid, signal_fire)
        # search a branch office in the range of the signal fire and move to it
        branch_offices = self.session.world.get_branch_offices()
        for bo in branch_offices:
            if bo.position.distance(signal_fire.position) <= signal_fire.radius and \
               bo.owner == signal_fire.owner:
                self.log.debug("Trader %s moving to bo %s", self.worldid, bo)
                self.allured_by_signal_fire[ship] = True

                # HACK: remove allured flag in a few ticks
                def rem_allured(self, ship):
                    self.allured_by_signal_fire[ship] = False

                Scheduler().add_new_object(Callback(rem_allured, self, ship),
                                           self,
                                           Scheduler().get_ticks(60))
                self.send_ship_random_branch(ship, bo)
                return
        self.log.debug("Trader can't find bo in range of the signal fire")
Esempio n. 7
0
    def run(self, seconds=0):
        """Provide a nice way to run the game for some time.

		Despite its name, this method will run the *game simulation* for X seconds.
		When the game is paused, the timer continues once the game unpauses.
		"""

        if not seconds:
            cooperative.schedule()
        else:
            # little hack because we don't have Python3's nonlocal
            class Flag(object):
                running = True

            def stop():
                Flag.running = False

            ticks = Scheduler().get_ticks(seconds)
            Scheduler().add_new_object(stop, None, run_in=ticks)

            while Flag.running:
                cooperative.schedule()
Esempio n. 8
0
    def reached_branch(self, ship):
        """Actions that need to be taken when reaching a branch office
		@param ship: ship instance"""
        self.log.debug("Trader %s ship %s: reached bo", self.worldid,
                       ship.worldid)
        settlement = self.office[ship.worldid].settlement
        # NOTE: must be sorted for mp games (same order everywhere)
        for res in sorted(settlement.buy_list.iterkeys(
        )):  # check for resources that the settlement wants to buy
            amount = self.session.random.randint(
                *TRADER.SELL_AMOUNT)  # select a random amount to sell
            if amount == 0:
                continue
            price = int(
                self.session.db.get_res_value(res) *
                TRADER.PRICE_MODIFIER_SELL * amount)
            settlement.buy(res, amount, price)
            # don't care if he bought it. the trader just offers.
            self.log.debug("Trader %s: offered sell %s tons of res %s",
                           self.worldid, amount, res)

        # NOTE: must be sorted for mp games (same order everywhere)
        for res in sorted(settlement.sell_list.iterkeys()):
            # select a random amount to buy from the settlement
            amount = self.session.random.randint(*TRADER.BUY_AMOUNT)
            if amount == 0:
                continue
            price = int(
                self.session.db.get_res_value(res) *
                TRADER.PRICE_MODIFIER_BUY * amount)
            settlement.sell(res, amount, price)
            self.log.debug("Trader %s: offered buy %s tons of res %s",
                           self.worldid, amount, res)

        del self.office[ship.worldid]
        # wait 2 seconds before going on to the next island
        Scheduler().add_new_object(Callback(self.ship_idle, ship), self, \
                                   Scheduler().get_ticks(TRADER.TRADING_DURATION))
        self.ships[ship] = self.shipStates.reached_branch
 def wreak_havoc(self, building):
     """Some inhabitants have to die."""
     super(BlackDeathDisaster, self)
     if building.inhabitants > 1:
         inhabitants_that_will_die = self._manager.session.random.randint(
             1, building.inhabitants)
         building.inhabitants -= inhabitants_that_will_die
         self.log.debug("%s inhabitants dying", inhabitants_that_will_die)
         Scheduler().add_new_object(Callback(self.wreak_havoc, building),
                                    self,
                                    run_in=self.TIME_BEFORE_HAVOC)
     else:
         self.recover(building)
Esempio n. 10
0
    def __init__(self, session, id, name, color, **kwargs):
        super(Pirate, self).__init__(session, id, name, color, **kwargs)

        # choose a random water tile on the coast and call it home
        self.home_point = self.session.world.get_random_possible_coastal_ship_position(
        )
        # random sea tile if costal tile not found. Empty map?
        if not self.home_point:
            self.home_point = self.session.world.get_random_possible_ship_position(
            )
        self.log.debug("Pirate: home at (%d, %d), radius %d",
                       self.home_point.x, self.home_point.y, self.home_radius)
        self.__init()

        # create a ship and place it randomly (temporary hack)
        for i in range(self.ship_count):
            self.create_ship_at_random_position()

        Scheduler().add_new_object(Callback(self.tick), self, 1, -1,
                                   self.tick_interval)
        Scheduler().add_new_object(Callback(self.tick_long), self, 1, -1,
                                   self.tick_long_interval)
Esempio n. 11
0
	def add(self, string_id, point=None, msg_type=None, message_dict=None, play_sound=True, check_duplicate=False):
		"""Adds a message to the MessageWidget.
		@param point: point where the action took place. Clicks on the message will then focus that spot.
		@param id: message id string, needed to retrieve the message text from the content database.
		@param msg_type: message type; determines what happens on click
		@param message_dict: dict with strings to replace in the message, e.g. {'player': 'Arthus'}
		@param play_sound: whether to play the default message speech for string_id
		@param check_duplicate: check for pseudo-duplicates (similar messages recently nearby)
		"""
		if check_duplicate:
			if string_id in self._last_message:
				when, where = self._last_message[string_id]
				if when > Scheduler().cur_tick - Scheduler().get_ticks(self.__class__._DUPLICATE_TIME_THRESHOLD) and \
				   where.distance(point) < self.__class__._DUPLICATE_SPACE_THRESHOLD:
					# there has been a message nearby recently, abort
					return
			self._last_message[string_id] = (Scheduler().cur_tick, point)

		sound = get_speech_file(string_id) if play_sound else None
		return self._add_message(_IngameMessage(point=point, id=string_id, msg_type=msg_type,
		                                        created=self.msgcount.next(), message_dict=message_dict),
		                         sound=sound)
Esempio n. 12
0
    def _load(self, db, worldid):
        super(Pirate, self)._load(db, worldid)
        self.__init()

        remaining_ticks, = db(
            "SELECT remaining_ticks FROM ai_pirate WHERE rowid = ?",
            worldid)[0]
        Scheduler().add_new_object(Callback(self.tick), self, remaining_ticks,
                                   -1, self.tick_interval)

        remaining_ticks_long, = db(
            "SELECT remaining_ticks_long FROM ai_pirate WHERE rowid = ?",
            worldid)[0]
        Scheduler().add_new_object(Callback(self.tick_long), self,
                                   remaining_ticks_long, -1,
                                   self.tick_interval)

        home = db("SELECT x, y FROM pirate_home_point")[0]
        self.home_point = Point(home[0], home[1])

        self.log.debug("Pirate: home at (%d, %d), radius %d",
                       self.home_point.x, self.home_point.y, self.home_radius)
Esempio n. 13
0
	def save_attacks(cls, db):
		"""
		Saves ongoing attacks
		"""
		calls = Scheduler().get_classinst_calls(Weapon)
		for call in calls:
			callback = call.callback
			weapon_id = callback.args[1]
			damage = callback.args[2]
			dest_x = callback.args[3].x
			dest_y = callback.args[3].y
			ticks = calls[call]
			db("INSERT INTO attacks(remaining_ticks, weapon_id, damage, dest_x, dest_y) VALUES (?, ?, ?, ?, ?)",
				ticks, weapon_id, damage, dest_x, dest_y)
	def remove_building(self, building):
		"""Called when a building is removed from the area (the building still exists during the call)."""
		if building.id in self.field_building_classes:
			# this can't be handled right now because the building still exists
			Scheduler().add_new_object(Callback(self._refresh_unused_fields), self, run_in=0)
			Scheduler().add_new_object(Callback(partial(super(ProductionBuilder, self).remove_building, building)), self, run_in=0)
		elif building.buildable_upon or building.id == BUILDINGS.TRAIL:
			pass # don't react to road, trees and ruined tents being destroyed
		else:
			self.register_change_list(list(building.position.tuple_iter()), BUILDING_PURPOSE.NONE, None)

			if building.id in self.collector_building_classes:
				self.collector_buildings.remove(building)
				self.simple_collector_area_cache.remove_building(building)
			elif building.id in self.production_building_classes:
				self.production_buildings.remove(building)

			if building.id == BUILDINGS.LUMBERJACK:
				self._handle_lumberjack_removal(building)
			elif building.id == BUILDINGS.FARM:
				self._handle_farm_removal(building)

			super(ProductionBuilder, self).remove_building(building)
Esempio n. 15
0
	def _changed(self):
		super()._changed()
		if not self._prod_line.save_statistics:
			return

		state = self._state.index
		current_tick = Scheduler().cur_tick

		if self._state_history and self._state_history[-1][0] == current_tick:
			self._state_history.pop() # make sure no two events are on the same tick
		if not self._state_history or self._state_history[-1][1] != state:
			self._state_history.append((current_tick, state))

		self._clean_state_history()
Esempio n. 16
0
    def begin_working(self):
        """Pretends that the collector works by waiting some time. finish_working is
		called after that time."""
        self.log.debug("%s begins working", self)
        assert self.job is not None, '%s job is None in begin_working' % self
        Scheduler().add_new_object(self.finish_working, self,
                                   self.work_duration)
        # play working sound
        if self.has_component(AmbientSoundComponent):
            am_comp = self.get_component(AmbientSoundComponent)
            if am_comp.soundfiles:
                am_comp.play_ambient(am_comp.soundfiles[0],
                                     position=self.position)
        self.state = self.states.working
    def __init__(self, x, y, slots=1, size=4, start_hidden=True, **kwargs):
        super(Collector, self).__init__(slots = slots, \
                                        size = size, \
                                        x = x, \
                                        y = y, \
                                        **kwargs)

        self.inventory.limit = size
        # TODO: use different storage to support multiple slots. see StorageHolder

        self.__init(self.states.idle, start_hidden)

        # start searching jobs just when construction (of subclass) is completed
        Scheduler().add_new_object(self.search_job, self, 1)
Esempio n. 18
0
	def load(self, db, worldid):
		super().load(db, worldid)
		runtime, action_set_id = db.get_concrete_object_data(worldid)
		# action_set_id should never be None in regular games,
		# but this information was lacking in savegames before rev 59.
		if action_set_id is None:
			action_set_id = self.__class__.get_random_action_set(level=self.level if hasattr(self, "level") else 0)
		self.__init(action_set_id)

		# delay setting of runtime until load of sub/super-class has set the action
		def set_action_runtime(self, runtime):
			# workaround to delay resolution of self._instance, which doesn't exist yet
			self._instance.setActionRuntime(runtime)
		Scheduler().add_new_object(Callback(set_action_runtime, self, runtime), self, run_in=0)
Esempio n. 19
0
def do_win(session):
	"""The player wins the current scenario."""
	PauseCommand().execute(session)
	show_db_message(session, 'YOU_HAVE_WON')
	horizons.globals.fife.play_sound('effects', "content/audio/sounds/events/scenario/win.ogg")

	continue_playing = session.gui.show_popup(_("You have won!"),
	                                          _("You have completed this scenario.") + u" " +
	                                          _("Do you want to continue playing?"),
	                                          show_cancel_button=True)
	if not continue_playing:
		Scheduler().add_new_object(Callback(session.gui.quit_session, force=True), session, run_in=0)
	else:
		UnPauseCommand().execute(session)
Esempio n. 20
0
	def infect(self, building, load=None):
		"""Infect a building with fire.
		@load: (db, disaster_worldid), set on restoring infected state of savegame"""
		super(FireDisaster, self).infect(building, load=load)
		# keep in sync with load()
		AddStatusIcon.broadcast(building, FireStatusIcon(building))
		NewDisaster.broadcast(building.owner, building, FireDisaster)
		self._affected_buildings.append(building)
		havoc_time = self.TIME_BEFORE_HAVOC
		if load:
			db, worldid = load
			havoc_time = db("SELECT remaining_ticks_havoc FROM fire_disaster WHERE disaster = ? AND building = ?", worldid, building.worldid)[0][0]

		Scheduler().add_new_object(Callback(self.wreak_havoc, building), self, run_in=havoc_time)