u16 Dialog::RecruitMonster(const Monster & monster, u16 available)
{
    Display & display = Display::Get();
    LocalEvent & le = LocalEvent::Get();

    // cursor
    Cursor & cursor = Cursor::Get();
    const Cursor::themes_t oldcursor = cursor.Themes();
    cursor.Hide();
    cursor.SetThemes(Cursor::POINTER);

    // calculate max count
    u32 max = 0;
    const payment_t paymentMonster = monster.GetCost();
    const Kingdom & kingdom = world.GetKingdom(Settings::Get().CurrentColor());

    while(kingdom.AllowPayment(paymentMonster * max) && max < available) ++max;

    u32 result = max;

    payment_t paymentCosts(paymentMonster * result);

    const Sprite & box = AGG::GetICN(ICN::RECRBKG, 0);
    const Rect pos((display.w() - box.w()) / 2, Settings::Get().QVGA() ? (display.h() - box.h()) / 2 - 15 : (display.h() - box.h()) / 2, box.w(), box.h());

    Background back(pos);
    back.Save();

    box.Blit(pos.x, pos.y);

    Point dst_pt;
    std::string str;
    Text text;

    // smear hardcore text "Cost per troop:"
    const Sprite & smear = AGG::GetICN(ICN::TOWNNAME, 0);
    dst_pt.x = pos.x + 144;
    dst_pt.y = pos.y + 55;
    smear.Blit(Rect(8, 1, 120, 12), dst_pt);

    text.Set(_("Cost per troop:"), Font::SMALL);
    dst_pt.x = pos.x + 206 - text.w() / 2;
    dst_pt.y = pos.y + 55;
    text.Blit(dst_pt);

    // text recruit monster
    str = _("Recruit %{name}");
    String::Replace(str, "%{name}", monster.GetMultiName());
    text.Set(str, Font::BIG);
    dst_pt.x = pos.x + (pos.w - text.w()) / 2;
    dst_pt.y = pos.y + 25;
    text.Blit(dst_pt);

    // sprite monster
    const Sprite & smon = AGG::GetICN(monster.ICNMonh(), 0);
    dst_pt.x = pos.x + 70 - smon.w() / 2;
    dst_pt.y = pos.y + 130 - smon.h();
    smon.Blit(dst_pt);

    bool extres = 2 == paymentMonster.GetValidItems();

    // info resource
    // gold
    const Sprite & sgold = AGG::GetICN(ICN::RESOURCE, 6);
    dst_pt.x = pos.x + (extres ? 150 : 175);
    dst_pt.y = pos.y + 75;
    sgold.Blit(dst_pt);

    dst_pt.x = pos.x + (extres ? 105 : 130);
    dst_pt.y = pos.y + 200;
    sgold.Blit(dst_pt);

    text.Set(GetString(paymentMonster.gold), Font::SMALL);
    dst_pt.x = pos.x + (extres ? 183 : 205) - text.w() / 2;
    dst_pt.y = pos.y + 103;
    text.Blit(dst_pt);

    // crystal
    if(paymentMonster.crystal)
    {
        const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 4);
	RedrawResourceInfo(sres, pos, paymentMonster.crystal,
				225, 75, 240, 103);
	dst_pt.x = pos.x + 180;
	dst_pt.y = pos.y + 200;
	sres.Blit(dst_pt);
    }
    else
    // mercury
    if(paymentMonster.mercury)
    {
        const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 1);
	RedrawResourceInfo(sres, pos, paymentMonster.mercury,
				225, 72, 240, 103);
	dst_pt.x = pos.x + 180;
	dst_pt.y = pos.y + 197;
	sres.Blit(dst_pt);
    }
    else
    // wood
    if(paymentMonster.wood)
    {
        const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 0);
	RedrawResourceInfo(sres, pos, paymentMonster.wood,
				225, 72, 240, 103);
	dst_pt.x = pos.x + 180;
	dst_pt.y = pos.y + 197;
	sres.Blit(dst_pt);
    }
    else
    // ore
    if(paymentMonster.ore)
    {
        const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 2);
	RedrawResourceInfo(sres, pos, paymentMonster.ore,
				225, 72, 240, 103);
	dst_pt.x = pos.x + 180;
	dst_pt.y = pos.y + 197;
	sres.Blit(dst_pt);
    }
    else
    // sulfur
    if(paymentMonster.sulfur)
    {
        const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 3);
	RedrawResourceInfo(sres, pos, paymentMonster.sulfur,
				225, 75, 240, 103);
	dst_pt.x = pos.x + 180;
	dst_pt.y = pos.y + 200;
	sres.Blit(dst_pt);
    }
    else
    // gems
    if(paymentMonster.gems)
    {
        const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 5);
	RedrawResourceInfo(sres, pos, paymentMonster.gems,
				225, 75, 240, 103);
	dst_pt.x = pos.x + 180;
	dst_pt.y = pos.y + 200;
	sres.Blit(dst_pt);
    }

    // text number buy
    text.Set(_("Number to buy:"));
    dst_pt.x = pos.x + 30;
    dst_pt.y = pos.y + 163;
    text.Blit(dst_pt);

    Background static_info(Rect(pos.x + 16, pos.y + 125, pos.w - 32, 122));
    static_info.Save();

    RedrawCurrentInfo(pos, available, result, paymentMonster, paymentCosts);

    // buttons
    dst_pt.x = pos.x + 34;
    dst_pt.y = pos.y + 249;
    Button buttonOk(dst_pt, ICN::RECRUIT, 8, 9);

    dst_pt.x = pos.x + 187;
    dst_pt.y = pos.y + 249;
    Button buttonCancel(dst_pt, ICN::RECRUIT, 6, 7);

    dst_pt.x = pos.x + 230;
    dst_pt.y = pos.y + 155;
    Button buttonMax(dst_pt, ICN::RECRUIT, 4, 5);
    dst_pt.x = pos.x + 208;
    dst_pt.y = pos.y + 156;
    Button buttonUp(dst_pt, ICN::RECRUIT, 0, 1);

    dst_pt.x = pos.x + 208;
    dst_pt.y = pos.y + 171;
    Button buttonDn(dst_pt, ICN::RECRUIT, 2, 3);

    buttonOk.Draw();
    buttonCancel.Draw();
    buttonMax.Draw();
    buttonUp.Draw();
    buttonDn.Draw();

    cursor.Show();
    display.Flip();

    bool redraw = false;

    // str loop
    while(le.HandleEvents())
    {
	le.MousePressLeft(buttonOk) ? buttonOk.PressDraw() : buttonOk.ReleaseDraw();
	le.MousePressLeft(buttonCancel) ? buttonCancel.PressDraw() : buttonCancel.ReleaseDraw();
	le.MousePressLeft(buttonMax) ? buttonMax.PressDraw() : buttonMax.ReleaseDraw();
	le.MousePressLeft(buttonUp) ? buttonUp.PressDraw() : buttonUp.ReleaseDraw();
	le.MousePressLeft(buttonDn) ? buttonDn.PressDraw() : buttonDn.ReleaseDraw();

	if(PressIntKey(0, max, result))
	{
	    paymentCosts = paymentMonster * result;
	    redraw = true;
	}

	if(le.MouseClickLeft(buttonUp) && result < max)
	{
	    ++result;
	    paymentCosts += paymentMonster;
	    redraw = true;
	}
	else
	if(le.MouseClickLeft(buttonDn) && result)
	{
	    --result;
	    paymentCosts -= paymentMonster;
	    redraw = true;
	}
	else
	if(le.MouseClickLeft(buttonMax) && result != max)
	{
	    result = max;
	    paymentCosts = paymentMonster * max;
	    redraw = true;
	}

	if(redraw)
	{
	    cursor.Hide();
	    static_info.Restore();
	    RedrawCurrentInfo(pos, available, result, paymentMonster, paymentCosts);
	    cursor.Show();
	    display.Flip();
	    redraw = false;
	}

	if(le.MouseClickLeft(buttonOk) || Game::HotKeyPress(Game::EVENT_DEFAULT_READY)) break;

	if(le.MouseClickLeft(buttonCancel) || Game::HotKeyPress(Game::EVENT_DEFAULT_EXIT)){ result = 0; break; }
    }

    cursor.Hide();

    back.Restore();
    cursor.SetThemes(oldcursor);

    cursor.Show();
    display.Flip();

    return result;
}
void Dialog::DwellingInfo(const Monster & monster, u16 available)
{
    Display & display = Display::Get();

    // cursor
    Cursor & cursor = Cursor::Get();
    const Cursor::themes_t oldcursor = cursor.Themes();
    cursor.Hide();
    cursor.SetThemes(cursor.POINTER);

    const payment_t paymentMonster = monster.GetCost();
    const Sprite & box = AGG::GetICN(ICN::RECR2BKG, 0);
    const Rect pos((display.w() - box.w()) / 2, (display.h() - box.h()) / 2, box.w(), box.h());

    Background back(pos);
    back.Save();

    box.Blit(pos.x, pos.y);

    LocalEvent & le = LocalEvent::Get();

    Point dst_pt;
    Text text;
    std::string str;

    // text recruit monster
    str = _("Recruit %{name}");
    String::Replace(str, "%{name}", monster.GetMultiName());
    text.Set(str, Font::BIG);
    text.Blit(pos.x + (pos.w - text.w()) / 2, pos.y + 25);

    // sprite monster
    const Sprite & smon = AGG::GetICN(monster.ICNMonh(), 0);
    dst_pt.x = pos.x + 70 - smon.w() / 2;
    dst_pt.y = pos.y + 120 - smon.h();
    smon.Blit(dst_pt);

    bool extres = 2 == paymentMonster.GetValidItems();

    // info resource
    // gold
    const Sprite & sgold = AGG::GetICN(ICN::RESOURCE, 6);
    dst_pt.x = pos.x + (extres ? 150 : 175);
    dst_pt.y = pos.y + 75;
    sgold.Blit(dst_pt);

    text.Set(GetString(paymentMonster.gold), Font::SMALL);
    dst_pt.x = pos.x + (extres ? 183 : 205) - text.w() / 2;
    dst_pt.y = pos.y + 103;
    text.Blit(dst_pt);
    // crystal
    if(paymentMonster.crystal)
    {
	const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 4);
	RedrawResourceInfo(sres, pos, paymentMonster.crystal,
				225, 75, 240, 103);
    }
    else
    // mercury
    if(paymentMonster.mercury)
    {
	const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 1);
	RedrawResourceInfo(sres, pos, paymentMonster.mercury,
				225, 72, 240, 103);
    }
    else
    // wood
    if(paymentMonster.wood)
    {
	const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 0);
	RedrawResourceInfo(sres, pos, paymentMonster.wood,
				225, 72, 240, 103);
    }
    else
    // ore
    if(paymentMonster.ore)
    {
	const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 2);
	RedrawResourceInfo(sres, pos, paymentMonster.ore,
				225, 72, 240, 103);
    }
    else
    // sulfur
    if(paymentMonster.sulfur)
    {
	const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 3);
	RedrawResourceInfo(sres, pos, paymentMonster.sulfur,
				225, 75, 240, 103);
    }
    else
    // gems
    if(paymentMonster.gems)
    {
	const Sprite & sres = AGG::GetICN(ICN::RESOURCE, 5);
	RedrawResourceInfo(sres, pos, paymentMonster.gems,
				225, 75, 240, 103);
    }

    // text available
    str = _("Available: %{count}");
    String::Replace(str, "%{count}", available);
    text.Set(str);
    text.Blit(pos.x + 70 - text.w() / 2, pos.y + 130);

    cursor.Show();
    display.Flip();

    //
    while(le.HandleEvents() && le.MousePressRight());

    cursor.Hide();

    back.Restore();
    cursor.SetThemes(oldcursor);

    cursor.Show();
    display.Flip();
}