@@ -293,6 +293,127 @@ auto facts_have_tag( const std::vector<proc::part_fact> &facts, const std::strin
293293 } );
294294}
295295
296+ auto join_sentences ( const std::vector<std::string> &sentences ) -> std::string
297+ {
298+ auto ret = std::string {};
299+ std::ranges::for_each ( sentences, [&]( const std::string & sentence ) {
300+ if ( sentence.empty () ) {
301+ return ;
302+ }
303+ if ( !ret.empty () ) {
304+ ret += ' ' ;
305+ }
306+ ret += sentence;
307+ } );
308+ return ret;
309+ }
310+
311+ auto primary_material_name ( const std::vector<proc::part_fact> &facts ) -> std::string
312+ {
313+ if ( std::ranges::any_of ( facts, [&]( const proc::part_fact & fact ) {
314+ return has_material ( fact, material_id ( " steel" ) ) || has_material ( fact, material_id ( " iron" ) );
315+ } ) ) {
316+ return " metal" ;
317+ }
318+ if ( std::ranges::any_of ( facts, [&]( const proc::part_fact & fact ) {
319+ return has_material ( fact, material_id ( " bone" ) );
320+ } ) ) {
321+ return " bone" ;
322+ }
323+ if ( std::ranges::any_of ( facts, [&]( const proc::part_fact & fact ) {
324+ return has_material ( fact, material_id ( " wood" ) );
325+ } ) ) {
326+ return " wooden" ;
327+ }
328+ return " simple" ;
329+ }
330+
331+ auto sword_base_description ( const std::string &name ) -> std::string
332+ {
333+ if ( name == " nail sword" ) {
334+ return " A rough wooden sword stiffened with driven nails." ;
335+ }
336+ if ( name == " crude sword" ) {
337+ return " A crude sword pieced together from wood and scavenged scrap." ;
338+ }
339+ if ( name == " hand-forged sword" ) {
340+ return " A serviceable sword built around a forged metal blade." ;
341+ }
342+ if ( name == " bone sword" ) {
343+ return " A rough sword built around a sharpened bone blade." ;
344+ }
345+ if ( name == " 2-by-sword" ) {
346+ return " A club-like sword carved from a sturdy length of wood." ;
347+ }
348+ return " A makeshift sword assembled from scavenged parts." ;
349+ }
350+
351+ auto sword_guard_phrase ( const std::vector<proc::part_fact> &guard_facts ) -> std::string
352+ {
353+ if ( guard_facts.empty () ) {
354+ return " no guard" ;
355+ }
356+ const auto material = primary_material_name ( guard_facts );
357+ if ( material == " metal" ) {
358+ return " a metal guard" ;
359+ }
360+ if ( material == " bone" ) {
361+ return " a bone guard" ;
362+ }
363+ if ( material == " wooden" ) {
364+ return " a wooden guard" ;
365+ }
366+ return " a simple guard" ;
367+ }
368+
369+ auto sword_grip_phrase ( const std::vector<proc::part_fact> &grip_facts ) -> std::string
370+ {
371+ if ( grip_facts.empty () ) {
372+ return {};
373+ }
374+ if ( has_itype ( grip_facts, itype_id ( " leather" ) ) || std::ranges::any_of ( grip_facts,
375+ [&]( const proc::part_fact & fact ) {
376+ return has_material ( fact, material_id ( " leather" ) );
377+ } ) ) {
378+ return " a leather-wrapped grip" ;
379+ }
380+ if ( has_itype ( grip_facts, itype_id ( " rag" ) ) || std::ranges::any_of ( grip_facts,
381+ [&]( const proc::part_fact & fact ) {
382+ return has_material ( fact, material_id ( " cotton" ) );
383+ } ) ) {
384+ return " a rag-wrapped grip" ;
385+ }
386+ return " a wrapped grip" ;
387+ }
388+
389+ auto sword_hilt_sentence ( const std::vector<proc::part_fact> &guard_facts,
390+ const std::vector<proc::part_fact> &grip_facts ) -> std::string
391+ {
392+ const auto guard_phrase = sword_guard_phrase ( guard_facts );
393+ const auto grip_phrase = sword_grip_phrase ( grip_facts );
394+ if ( grip_phrase.empty () ) {
395+ return string_format ( " The hilt uses %s." , guard_phrase );
396+ }
397+ return string_format ( " The hilt uses %s and %s." , guard_phrase, grip_phrase );
398+ }
399+
400+ auto sword_reinforcement_sentence ( const std::vector<proc::part_fact> &reinforcement_facts ) ->
401+ std::string
402+ {
403+ const auto has_nails = has_itype ( reinforcement_facts, itype_id ( " nail" ) );
404+ const auto has_scrap = has_itype ( reinforcement_facts, itype_id ( " scrap" ) );
405+ if ( has_nails && has_scrap ) {
406+ return " Driven nails and scrap reinforcement add stiffness at the cost of weight." ;
407+ }
408+ if ( has_nails ) {
409+ return " Driven nails add stiffness and a little puncturing power." ;
410+ }
411+ if ( has_scrap ) {
412+ return " Scrap reinforcement adds weight and stiffness." ;
413+ }
414+ return {};
415+ }
416+
296417auto matching_slot_uses ( const proc::schema &sch, const proc::part_fact &fact ) -> int
297418{
298419 auto uses = 0 ;
@@ -427,6 +548,20 @@ auto sword_name( const proc::schema &sch, const std::vector<proc::part_fact> &fa
427548 return " sword" ;
428549}
429550
551+ auto sword_description ( const proc::schema &sch, const std::vector<proc::part_fact> &facts,
552+ const std::vector<proc::craft_pick> &picks,
553+ const std::string &name ) -> std::string
554+ {
555+ const auto guard_facts = picked_facts_for_role ( sch, facts, picks, " guard" );
556+ const auto grip_facts = picked_facts_for_role ( sch, facts, picks, " grip" );
557+ const auto reinforcement_facts = picked_facts_for_role ( sch, facts, picks, " reinforcement" );
558+ return join_sentences ( {
559+ sword_base_description ( name ),
560+ sword_hilt_sentence ( guard_facts, grip_facts ),
561+ sword_reinforcement_sentence ( reinforcement_facts ),
562+ } );
563+ }
564+
430565auto sandwich_name ( const proc::schema &sch, const std::vector<proc::part_fact> &facts,
431566 const std::vector<proc::craft_pick> &picks ) -> std::string
432567{
@@ -577,6 +712,7 @@ auto sword_preview( const proc::schema &sch, const std::vector<proc::part_fact>
577712 blob.melee .to_hit = std::clamp ( ( edge_score + bash_score ) / 18 - blob.mass_g / 900 , -2 , 4 );
578713 blob.melee .dur = std::max ( 1 , dur_score + blob.mass_g / 250 );
579714 blob.name = sword_name ( sch, facts, picks );
715+ blob.description = sword_description ( sch, facts, picks, blob.name );
580716 return blob;
581717}
582718
0 commit comments