def set_slot_info(self, slot_id, resource_id, selling, limit): assert resource_id is not None self.log.debug( "BuySellTab: setting slot %d to resource %d, selling=%s, limit %d", slot_id, resource_id, selling, limit) self.slot_widgets[slot_id].action = "sell" if selling else "buy" if self.inited: SetTradeSlot(self.trade_post, slot_id, resource_id, selling, limit).execute(self.session)
def test_trade(gui): """ """ ship = get_player_ship(gui.session) gui.select([ship]) # ally players so they can trade world = gui.session.world for player in world.players: if player is not ship.owner: world.diplomacy.add_ally_pair( ship.owner, player ) # move ship near foreign warehouse and wait for it to arrive move_ship(gui, ship, (68, 23)) # click trade button gui.trigger('overview_trade_ship', 'trade') # trade widget visible assert gui.find(name='buy_sell_goods') ship_inv = ship.get_component(StorageComponent).inventory settlement = gui.session.world.islands[0].settlements[0] settlement_inv = settlement.get_component(StorageComponent).inventory # transfer 1 t gui.trigger('buy_sell_goods', 'size_1') old_ship_value = ship_inv[RES.BOARDS] old_settlement_value = settlement_inv[RES.BOARDS] # of boards (will be bought) gui.trigger('buy_sell_goods', 'inventory_entry_0') assert old_settlement_value + 1 == settlement_inv[RES.BOARDS] assert old_ship_value - 1 == ship_inv[RES.BOARDS] old_ship_value = ship_inv[RES.CANNON] old_settlement_value = settlement_inv[RES.CANNON] # now cannons (won't be bought) gui.trigger('buy_sell_goods', 'inventory_entry_3') assert old_settlement_value == settlement_inv[RES.CANNON] assert old_ship_value == ship_inv[RES.CANNON] # the ai has to want more boards trade_post = settlement.get_component(TradePostComponent) assert settlement_inv[RES.BOARDS] < trade_post.slots[trade_post.buy_list[RES.BOARDS]].limit # transfer 50 t of boards gui.trigger('buy_sell_goods', 'size_5') gui.trigger('buy_sell_goods', 'inventory_entry_0') # now it has enough assert settlement_inv[RES.BOARDS] == trade_post.slots[trade_post.buy_list[RES.BOARDS]].limit old_ship_value = ship_inv[RES.BOARDS] # so another click won't do anything gui.trigger('buy_sell_goods', 'inventory_entry_0') assert old_ship_value == ship_inv[RES.BOARDS] # no matter how small the amount gui.trigger('buy_sell_goods', 'size_1') gui.trigger('buy_sell_goods', 'inventory_entry_0') assert old_ship_value == ship_inv[RES.BOARDS] # make room on ship inventory ship_inv.alter(RES.BOARDS, - ship_inv[RES.BOARDS]) # test sell now, give settlement something to sell SetTradeSlot(trade_post, 2, RES.ALVEARIES, True, 5)(settlement.owner) settlement.get_component(StorageComponent).inventory.alter(RES.ALVEARIES, 10) # this gives us 5 alevaries assert ship_inv[RES.ALVEARIES] == 0 # first transfer one gui.trigger('buy_sell_goods', 'size_1') gui.trigger('buy_sell_goods', 'buy_sell_inventory_True_entry_1') print ship_inv[RES.ALVEARIES] assert ship_inv[RES.ALVEARIES] == 1 assert settlement_inv[RES.ALVEARIES] == 9 # now transfer 5, should actually transfer 4 gui.trigger('buy_sell_goods', 'size_2') gui.trigger('buy_sell_goods', 'buy_sell_inventory_True_entry_1') assert ship_inv[RES.ALVEARIES] == 5 assert settlement_inv[RES.ALVEARIES] == 5
def test_tutorial(gui): """Test the tutorial scenario.""" # FIXME disable disasters (this should be an option for a scenario) gui.session.world.disaster_manager.disabled = True def assert_progress(progress): wait_and_close_logbook(gui) assert var_eq(gui.session, 'tutorial_progress', progress) # Tutorial start assert_progress(16) # Goal: Build warehouse ship = get_player_ship(gui.session) move_ship(ship, (11, 1)) gui.select([ship]) gui.trigger('overview_trade_ship', 'found_settlement') gui.cursor_click(11, 6, 'left') # Goal: Build a lumberjack assert_progress(19) # lumberjack (2) gui.trigger('mainhud', 'build') gui.trigger('tab', 'button_03') gui.cursor_click(8, 10, 'left', shift=True) gui.cursor_click(13, 10, 'left') gui.cursor_click(13, 10, 'right') # roads gui.trigger('tab', 'button_21') gui.cursor_multi_click((10, 8), (10, 9), (10, 10), (11, 10)) # Goal: Build hunter and fisher assert_progress(22) # fisher gui.trigger('tab', 'button_33') gui.cursor_click(13, 6, 'left') # hunter gui.trigger('tab', 'button_23') gui.cursor_click(8, 8, 'left') # Goal: Mainsquare assert_progress(25) gui.trigger('tab', 'button_02') gui.cursor_click(15, 18, 'left') # Goal: first tent assert_progress(28) # roads gui.trigger('tab', 'button_21') gui.cursor_multi_click((13, 15), (14, 15), (16, 15), (17, 15), (18, 15), (19, 15), (20, 15)) # tent gui.trigger('tab', 'button_01') gui.cursor_click(13, 13, 'left') # Goal: 4 tents assert_progress(31) gui.trigger('tab', 'button_01') gui.cursor_multi_click((15, 13), (17, 13), (19, 13)) # Goal: Build a signal fire assert_progress(34) # wait until we have enough boards while not settlement_res_stored_greater(gui.session, RES.BOARDS, 5): gui.run() gui.trigger('tab', 'button_22') gui.cursor_click(9, 5, 'left') # Goal: Trading assert_progress(37) # TODO do this with the gui (needs named buttons and a way to control the slider) player = gui.session.world.player tradepost = player.settlements[0].get_component(TradePostComponent) SetTradeSlot(tradepost, 0, RES.TOOLS, False, 30)(player) # Goal: Pavilion assert_progress(40) # wait until we have enough boards while not settlement_res_stored_greater(gui.session, RES.BOARDS, 5): gui.run() gui.trigger('tab', 'button_12') gui.cursor_click(19, 16, 'left') # Goal: Next tier assert_progress(43) # TODO adjust settler taxes # wait until settlers upgraded while not settler_level_greater(gui.session, TIER.SAILORS): gui.run() # Goal: Farm assert_progress(46) # wait until we have enough boards while not settlement_res_stored_greater(gui.session, RES.BOARDS, 10): gui.run() gui.trigger('tab_base', '1') # FIXME this sometimes fails gui.trigger('tab', 'button_02') gui.cursor_click(25, 12, 'left') # Goal: Fields assert_progress(49) gui.trigger('tab_base', '1') # potato gui.trigger('tab', 'button_12') gui.cursor_click(23, 11, 'left') # pasture gui.trigger('tab', 'button_22') gui.cursor_click(21, 10, 'left') # Goal: Storage assert_progress(52) # remove a tree to connect to farm gui.trigger('mainhud', 'destroy_tool') gui.cursor_click(21, 15, 'left') # roads gui.trigger('mainhud', 'build') gui.trigger('tab_base', '0') gui.trigger('tab', 'button_21') gui.cursor_multi_click((21, 15), (22, 15), (23, 15), (24, 15), (24, 14)) # storage tent gui.trigger('tab', 'button_11') gui.cursor_click(21, 16, 'left') # Goal: Weaver assert_progress(55) # wait until we have enough boards while not settlement_res_stored_greater(gui.session, RES.BOARDS, 10): gui.run() gui.trigger('tab_base', '1') gui.trigger('tab', 'button_21') gui.cursor_click(25, 14, 'left') # Goal: 50 inhabitants, positive balance assert_progress(58) # more potatoe fields gui.trigger('tab_base', '1') gui.trigger('tab', 'button_12') gui.cursor_multi_click((24, 9), (27, 8), (27, 11)) # lumberjack (more wood for upgrades) gui.trigger('tab_base', '0') gui.trigger('tab', 'button_03') gui.cursor_click(19, 18, 'left') # wait until we have enough boards while not settlement_res_stored_greater(gui.session, RES.BOARDS, 39): gui.run() # tents gui.trigger('tab', 'button_01') gui.cursor_multi_click((11, 14), (11, 15), (12, 17), (11, 20), (12, 22), (14, 22), (16, 22), (18, 22), (19, 20), (22, 15)) # Goal: Won assert_progress(61) assert_win(gui)
def manager_buysell(self): """Calculate the required inventory levels and make buy/sell decisions based on that.""" managed_resources = [ RES.TOOLS, RES.BOARDS, RES.BRICKS, RES.FOOD, RES.TEXTILE, RES.LIQUOR, RES.TOBACCO_PRODUCTS, RES.SALT, RES.CANNON, RES.MEDICAL_HERBS ] settlement = self.settlement_manager.settlement assert isinstance(settlement, Settlement) inventory = settlement.get_component(StorageComponent).inventory session = self.settlement_manager.session gold = self.settlement_manager.owner.get_component( StorageComponent).inventory[RES.GOLD] buy_sell_list = [ ] # [(importance (lower is better), resource_id, limit, sell), ...] for resource_id in managed_resources: current_requirement = self.get_current_resource_requirement( resource_id) self.resource_requirements[resource_id] = current_requirement max_buy = int( round(current_requirement * self.personality.buy_threshold)) # when to stop buying if 0 < current_requirement <= self.personality.low_requirement_threshold: # avoid not buying resources when very little is needed in the first place max_buy = current_requirement min_sell = int( round( current_requirement * self.personality.sell_threshold)) # when to start selling if inventory[resource_id] < max_buy: # have 0, need 100, max_buy 67, importance -0.0434 # have 0, need 30, max_buy 20, importance -0.034 # have 10, need 30, max_buy 20, importance 0.288 # have 19, need 30, max_buy 20, importance 0.578 # have 66, need 100, max_buy 67, importance 0.610 importance = inventory[resource_id] / float( current_requirement + 1) - math.log(max_buy + 10) / 100 buy_sell_list.append((importance, resource_id, max_buy, False)) elif inventory[resource_id] > min_sell: price = int( session.db.get_res_value(resource_id) * TRADER.PRICE_MODIFIER_BUY) # have 50, need 30, min_sell 40, gold 5000, price 15, importance 0.08625 # have 100, need 30, min_sell 40, gold 5000, price 15, importance 0.02464 # have 50, need 30, min_sell 40, gold 0, price 15, importance 0.05341 # have 50, need 20, min_sell 27, gold 5000, price 15, importance 0.07717 # have 28, need 20, min_sell 27, gold 5000, price 15, importance 0.23150 # have 28, need 20, min_sell 27, gold 0, price 15, importance 0.14335 # have 50, need 30, min_sell 40, gold 10000000, price 15, importance 0.16248 # have 40, need 30, min_sell 40, gold 5000, price 30, importance 0.04452 importance = 100.0 / (inventory[resource_id] - min_sell + 10) / (current_requirement + 1) * math.log(gold + 200) / (price + 1) buy_sell_list.append((importance, resource_id, min_sell, True)) if not buy_sell_list: return # nothing to buy nor sell trade_post = settlement.get_component(TradePostComponent) trade_slots = trade_post.slots num_slots = len(trade_slots) sell_list = trade_post.sell_list buy_list = trade_post.buy_list # discard the less important buy/sell wishes buy_sell_list = sorted(buy_sell_list)[:num_slots] bought_sold_resources = list(zip(*buy_sell_list))[1] # clear all slots we will no longer be needing for resource_id in managed_resources: if resource_id in bought_sold_resources: sell = buy_sell_list[bought_sold_resources.index( resource_id)][3] if sell and resource_id in buy_list: ClearTradeSlot(trade_post, buy_list[resource_id]).execute(session) elif not sell and resource_id in sell_list: ClearTradeSlot(trade_post, sell_list[resource_id]).execute(session) else: if resource_id in buy_list: ClearTradeSlot(trade_post, buy_list[resource_id]).execute(session) elif resource_id in sell_list: ClearTradeSlot(trade_post, sell_list[resource_id]).execute(session) # add any new offers for resource_id in managed_resources: if resource_id in bought_sold_resources: limit, sell = buy_sell_list[bought_sold_resources.index( resource_id)][2:] if sell and ( resource_id not in sell_list or trade_slots[sell_list[resource_id]].limit != limit): SetTradeSlot(trade_post, trade_post.get_free_slot(resource_id), resource_id, True, limit).execute(session) elif not sell and ( resource_id not in buy_list or trade_slots[buy_list[resource_id]].limit != limit): SetTradeSlot(trade_post, trade_post.get_free_slot(resource_id), resource_id, False, limit).execute(session)