Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Quietust

Pages: 1 ... 4 5 [6] 7 8 ... 560
76
DF Suggestions / Re: Browsing history while it is being generated
« on: January 24, 2022, 01:23:13 pm »
Related to that same point, judging by the last sentence in the devlog, world generation might need to be paused to enable timely player interaction (in the mythy-much-later update).

This sounds like a case where multithreading would be quite helpful and also not a massive ordeal (unlike the usual multithreading suggestions). You wouldn't be trying to separate individual events in a tangled web of cause and effect (like in fort mode), you'd just be making a browsing window in a separate thread to worldgen. Incidentally, this approach would also come with potential benefits other than just responsive windows for legends browsing, such as being able to generate multiple worlds at a time, each on its own CPU core, or even playing in an already created world while you generate a new one.

Worldgen would need to be paused occasionally to an extent if you wanted to pipe more information from the "worldgen thread" to the "legends browser thread", but this pausing could be done far less often than you would need to if you were trying to pause enough to keep a browser responsive (once every second or few seconds, vs the dozen times a second to make a browser responsive, and probably still feeling clunky).

You could also conceivably not update the legend browser automatically and just have a button to "update legends" with the new information.
One thing which never came up in your original thread is that before you could consider generating multiple worlds in multiple threads, the game would first need to be modified in order to allow multiple worlds to be loaded simultaneously, and that would actually require some very significant changes and likely result in a performance loss when playing with just one world (because everything would need to know which world it was looking at).

On the other hand, putting the UI on a separate thread from the actual world generation process (while still keeping it "one world at a time") would still require the addition of synchronization logic in many different places - otherwise, adding a new record to a list (e.g. a new civilization, site, historical figure, or just a history event) is likely to be non-atomic, and if the code that updates the list is interrupted by another thread, the list could very briefly end up in an inconsistent state where trying to access its contents could cause the game to crash, and even worse things could happen if worldgen tried to remove something while the UI was trying to display it (e.g. if a world got Rejected and it had to start over from scratch).

77
DF Gameplay Questions / Re: How can I create a prepared meals stockpile?
« on: January 20, 2022, 08:21:22 am »
I suppose you can disregard my comment about stack size - I only play older versions of DF, and I'm still used to barrels only being able to hold 10 items apiece and huge stacks of 100+ prepared meals not fitting inside them at all.

78
DF Gameplay Questions / Re: How can I create a prepared meals stockpile?
« on: January 18, 2022, 03:36:34 pm »
The main advantage of making Lavish meals is that you'll end up with larger stacks, allowing you to fit more meals in a given amount of space (assuming you don't mess with minecarts or quantum stockpiling). It also tends to make the meals more valuable (since they have more ingredients), but it also results in your cooks getting less experience (since they only gain experience for each cooking job, not for each individual meal produced in the stack).

79
DF Gameplay Questions / Re: Questions about glass floors
« on: January 15, 2022, 05:52:04 pm »
The answer is actually more nonsensical, although less frustrating: Although they do not let light in (for purposes of vision), all spaces that are blocked only by constructed floors (with no natural ground above them) are considered "outside" for purposes of cave adaptation, regardless of floor material.

You're mixing things up a bit - tiles which were exposed to the sky and then covered by constructions are Light and Inside.

As for Cave Adaptation, all of the mechanics can be found on the wiki - "Dark" tiles cause adaptation to increase (while "Light" tiles do not), and "Outside" tiles trigger the negative effects (and gradually cause adaptation to decrease). What this means is that standing under a constructed floor will have no effect on cave adaptation whatsoever - it won't make it better or worse.

80
DF Gameplay Questions / Re: Questions about glass floors
« on: January 15, 2022, 02:42:25 pm »
All constructed walls and floors are opaque and effectively indestructible, regardless of their material.

81
DF Gameplay Questions / Re: Skill Lists Without Dwarf Therapist
« on: January 07, 2022, 03:37:56 pm »
Unfortunately, no there isn't - that's one of the main reasons why Dwarf Therapist exists.

DFHack could be used to add that screen into the game itself (and it could also add a screen that does the same thing as Dwarf Therapist - see "Dwarf Manipulator"), but that would arguably be even less Vanilla than using Dwarf Therapist.

If you want to stay "as vanilla as possible", then you're going to have to do without all of these things - in order to find a dwarf with a particular skill, you'd either have to manually check all of them one-by-one or you'd have to keep a notebook on your desk where you can keep track of each dwarf's skills and assignments (and periodically recheck them to keep track of when their skills improve and/or get rusty).

82
DF Gameplay Questions / Re: Can enemies destroy your walls and bridges?
« on: December 31, 2021, 11:21:26 am »
The current siege behavior is that sieges last for either one season or one year (random), apart from a small number of anomalous durations reported from credible sources.
In older versions (i.e. 0.34.11 and earlier), sieges from Human civilizations (and anything else with [SIEGER]) lasted 1 year while other sieges else lasted 1 season. I'm not sure how Undead Invasions were treated, though.

83
DF Gameplay Questions / Re: Can enemies destroy your walls and bridges?
« on: December 30, 2021, 10:39:52 am »
During siege, can goblins, necromancer armies, etc. destroy your walls and/or bridges?
No. The only way bridges can be destroyed is if you try to use them to atom-smash something excessively large, or if they get melted (e.g. from magma or from dragonfire).
Do they use siege equipment like catapults/ballistas etc.?
No.

84
DF Gameplay Questions / Re: So I tried to fill my reservoir…
« on: December 11, 2021, 08:27:40 am »
The "clean" command can remove mud, but it doesn't seem to be selective.
There is also a "spotclean" command that can clean individual tiles.

85
Utilities and 3rd Party Applications / Re: DFHack 0.47.05-r3
« on: December 09, 2021, 02:10:11 pm »
That might be the one thing you can't do with tiletypes - there's no MUDDY FLOOR shape, no MUDDY STONE material, no MUDDY special, and no Muddy option.
That's because there is no generic "MUDDY" flag (like there was back in 40d) - you have to create a "material_spatter" event with its material set to MUD:NONE (and state set to SOLID), add it to the map block in question, then set the "amount" for the appropriate tile within it.

Unfortunately, there don't appear to be any plugins or scripts which do this, but it shouldn't be too difficult to write a new one - it's mostly the same process as creating new mineral veins (which is supported within at least one plugin).

Out of curiosity, is it the spatter that facilitates farming, or does another flag get set when the spatter is detected?
I haven't checked, but I suspect it's the spatter itself that permits farm plot placement since there's no "mud" flag in tile_occupancy/tile_designation (like there was in 40d and earlier).

86
Utilities and 3rd Party Applications / Re: DFHack 0.47.05-r3
« on: December 08, 2021, 10:28:12 am »
That might be the one thing you can't do with tiletypes - there's no MUDDY FLOOR shape, no MUDDY STONE material, no MUDDY special, and no Muddy option.
That's because there is no generic "MUDDY" flag (like there was back in 40d) - you have to create a "material_spatter" event with its material set to MUD:NONE (and state set to SOLID), add it to the map block in question, then set the "amount" for the appropriate tile within it.

Unfortunately, there don't appear to be any plugins or scripts which do this, but it shouldn't be too difficult to write a new one - it's mostly the same process as creating new mineral veins (which is supported within at least one plugin).

87
DF Suggestions / Re: Dwarves changing their preferences
« on: December 06, 2021, 08:34:42 am »
As of right now, Dwarves never hate "things" or even animals in general - they only hate Vermin, so adding general negative preferences would presumably need to happen first.

88
DF General Discussion / Re: Future of the Fortress
« on: December 03, 2021, 07:22:43 pm »

in a similar vein: is there any chance of updating the forums to https? http is rather antiquated at this point - my browser complains every time i open the site, lol.

I think part of the reason it doesn't use SSL is because most people here have externally-hosted avatar images, and having HTTP images in an HTTPS page tends to result in "mixed content" security warnings. Of course, it also seems to require HTTP URLs for avatars, so that doesn't really help things much...

89
For the record, the reason BUILDINGDESTROYERs actively seek out buildings is to make things like Trolls and Megabeasts more dangerous - they can't find a path into your fortress if all of your doors are locked, so by deliberately finding and smashing them they can make an entrance.

90
DF Modding / Re: Historical figure personality analysis science
« on: December 01, 2021, 08:44:23 am »
So is there a way of translating that into math? Is it just adding up the values of those four traits?
The actual math is done inside this pair of functions:
Code: [Select]
                             int __thiscall unit_personality::getOverallScore(unit_pe
             int               EAX:4           <RETURN>
             unit_personali    RCX:8 (auto)    this
             int32_t[50] *     RDX:8           weights
                              unit_personality::getOverallScore
 140910ae0   0    48 89 5c 24 08  MOV      qword ptr [RSP + local_res8],RBX
 140910ae5   0    48 89 6c 24 10  MOV      qword ptr [RSP + local_res10],RBP
 140910aea   0    48 89 74 24 18  MOV      qword ptr [RSP + local_res18],RSI
 140910aef   0    57              PUSH     RDI
 140910af0 008    48 83 ec 20     SUB      RSP,0x20
 140910af4 028    33 f6           XOR      ESI,ESI
 140910af6 028    48 8b fa        MOV      RDI,RDX
 140910af9 028    0f b7 de        MOVZX    EBX,SI
 140910afc 028    48 8b e9        MOV      RBP,RCX
 140910aff 028    90              NOP
                              LAB_140910b00                                      XREF[1]:   140910b34(j) 
 140910b00 028    44 8b 07        MOV      R8D,dword ptr [RDI]
 140910b03 028    45 85 c0        TEST     R8D,R8D
 140910b06 028    7e 0f           JLE      LAB_140910b17
 140910b08 028    0f bf d3        MOVSX    EDX,BX
 140910b0b 028    48 8b cd        MOV      RCX,RBP
 140910b0e 028    e8 3d 00 00 00  CALL     unit_personality::checkTrait                                int checkTrait(unit_personality
 140910b13 028    03 f0           ADD      ESI,EAX
 140910b15 028    eb 12           JMP      LAB_140910b29
                              LAB_140910b17                                      XREF[1]:   140910b06(j) 
 140910b17 028    79 10           JNS      LAB_140910b29
 140910b19 028    41 f7 d8        NEG      R8D
 140910b1c 028    0f bf d3        MOVSX    EDX,BX
 140910b1f 028    48 8b cd        MOV      RCX,RBP
 140910b22 028    e8 29 00 00 00  CALL     unit_personality::checkTrait                                int checkTrait(unit_personality
 140910b27 028    2b f0           SUB      ESI,EAX
                              LAB_140910b29                                      XREF[2]:   140910b15(j), 140910b17(j) 
 140910b29 028    66 ff c3        INC      BX
 140910b2c 028    48 83 c7 04     ADD      RDI,0x4
 140910b30 028    66 83 fb 32     CMP      BX,0x32
 140910b34 028    7c ca           JL       LAB_140910b00
 140910b36 028    48 8b 5c 24 30  MOV      RBX,qword ptr [RSP + local_res8+0x28]
 140910b3b 028    8b c6           MOV      EAX,ESI
 140910b3d 028    48 8b 74 24 40  MOV      RSI,qword ptr [RSP + local_res18+0x28]
 140910b42 028    48 8b 6c 24 38  MOV      RBP,qword ptr [RSP + local_res10+0x28]
 140910b47 028    48 83 c4 20     ADD      RSP,0x20
 140910b4b 008    5f              POP      RDI
 140910b4c   0    c3              RET

...

                             int __thiscall unit_personality::checkTrait(unit_persona
             int               EAX:4           <RETURN>
             unit_personali    RCX:8 (auto)    this
             personality_fa    EDX:4           type
             int               R8D:4           rolls
                              unit_personality::checkTrait
 140910b50   0    48 89 5c 24 10  MOV      qword ptr [RSP + local_res10],RBX
 140910b55   0    57              PUSH     RDI
 140910b56 008    48 83 ec 20     SUB      RSP,0x20
 140910b5a 028    41 8b d8        MOV      EBX,R8D
 140910b5d 028    4c 63 c2        MOVSXD   R8,EDX
 140910b60 028    48 8b 91 58     MOV      RDX,qword ptr [RCX + 0x158]
                   01 00 00
 140910b67 028    42 0f b7 84     MOVZX    EAX,word ptr [RCX + R8*0x2 + 0x80]
                   41 80 00 00 00
 140910b70 028    48 85 d2        TEST     RDX,RDX
 140910b73 028    74 16           JZ       LAB_140910b8b
 140910b75 028    66 42 03 04 42  ADD      AX,word ptr [RDX + R8*0x2]
 140910b7a 028    79 04           JNS      LAB_140910b80
 140910b7c 028    33 c0           XOR      EAX,EAX
 140910b7e 028    eb 0b           JMP      LAB_140910b8b
                              LAB_140910b80                                      XREF[1]:   140910b7a(j) 
 140910b80 028    66 83 f8 64     CMP      AX,0x64
 140910b84 028    7e 05           JLE      LAB_140910b8b
 140910b86 028    b8 64 00 00 00  MOV      EAX,0x64
                              LAB_140910b8b                                      XREF[3]:   140910b73(j), 140910b7e(j),
                                                                                             140910b84(j) 
 140910b8b 028    33 ff           XOR      EDI,EDI
 140910b8d 028    85 db           TEST     EBX,EBX
 140910b8f 028    7e 5d           JLE      LAB_140910bee
                              LAB_140910b91                                      XREF[4]:   14106e98c(*), 14106e99c(*),
                                                                                             141ef2ec0(*), 141ef2ec8(*) 
 140910b91 028    48 89 74 24 30  MOV      qword ptr [RSP + local_res8+0x28],RSI
 140910b96 028    0f bf f0        MOVSX    ESI,AX
 140910b99 028    ff c6           INC      ESI
 140910b9b 028    0f 1f 44 00 00  NOP      dword ptr [RAX + RAX*0x1]
                              LAB_140910ba0                                      XREF[1]:   140910be7(j) 
 140910ba0 028    83 fe 01        CMP      ESI,0x1
 140910ba3 028    77 04           JA       LAB_140910ba9
 140910ba5 028    33 c0           XOR      EAX,EAX
 140910ba7 028    eb 38           JMP      LAB_140910be1
                              LAB_140910ba9                                      XREF[1]:   140910ba3(j) 
 140910ba9 028    e8 12 b5 0e 00  CALL     mt_trandom                                                  int32_t mt_trandom(void)
 140910bae 028    44 8b c0        MOV      R8D,EAX
 140910bb1 028    b8 03 00 00 00  MOV      EAX,0x3
 140910bb6 028    41 f7 e0        MUL      R8D
 140910bb9 028    41 8b c0        MOV      EAX,R8D
 140910bbc 028    2b c2           SUB      EAX,EDX
 140910bbe 028    d1 e8           SHR      EAX,1
 140910bc0 028    03 c2           ADD      EAX,EDX
 140910bc2 028    33 d2           XOR      EDX,EDX
 140910bc4 028    c1 e8 1e        SHR      EAX,0x1e
 140910bc7 028    69 c0 ff ff     IMUL     EAX,EAX,0x7fffffff
                   ff 7f
 140910bcd 028    44 2b c0        SUB      R8D,EAX
 140910bd0 028    b8 ff ff ff 7f  MOV      EAX,0x7fffffff
 140910bd5 028    f7 f6           DIV      ESI
 140910bd7 028    33 d2           XOR      EDX,EDX
 140910bd9 028    8d 48 01        LEA      ECX,[RAX + 0x1]
 140910bdc 028    41 8b c0        MOV      EAX,R8D
 140910bdf 028    f7 f1           DIV      ECX
                              LAB_140910be1                                      XREF[1]:   140910ba7(j) 
 140910be1 028    03 f8           ADD      EDI,EAX
 140910be3 028    ff cb           DEC      EBX
 140910be5 028    85 db           TEST     EBX,EBX
 140910be7 028    7f b7           JG       LAB_140910ba0
 140910be9 028    48 8b 74 24 30  MOV      RSI,qword ptr [RSP + local_res8+0x28]
                              LAB_140910bee                                      XREF[3]:   140910b8f(j), 141ef2ecc(*),
                                                                                             141ef2ed4(*) 
 140910bee 028    8b c7           MOV      EAX,EDI
 140910bf0 028    48 8b 5c 24 38  MOV      RBX,qword ptr [RSP + local_res10+0x28]
 140910bf5 028    48 83 c4 20     ADD      RSP,0x20
 140910bf9 008    5f              POP      RDI
 140910bfa   0    c3              RET

Also, I mentioned that it's all x86 assembly, but Ghidra is also able to produce a reasonable approximation of C code:
Code: [Select]
int __thiscall unit_personality::getOverallScore(unit_personality *this,int32_t (*weights) [50])

{
  int iVar1;
  short sVar2;
  int iVar3;
 
  iVar3 = 0;
  sVar2 = 0;
  do {
    iVar1 = (*weights)[0];
    if (iVar1 < 1) {
      if (iVar1 < 0) {
        iVar1 = checkTrait(this,(int)sVar2,-iVar1);
        iVar3 -= iVar1;
      }
    }
    else {
      iVar1 = checkTrait(this,(int)sVar2,iVar1);
      iVar3 += iVar1;
    }
    sVar2 += 1;
    weights = (int32_t (*) [50])(*weights + 1);
  } while (sVar2 < 0x32);
  return iVar3;
}

int __thiscall
unit_personality::checkTrait(unit_personality *this,personality_facet_type type,int rolls)

{
  uint16_t uVar1;
  uint uVar2;
  int iVar3;
 
  uVar1 = (&(this->traits).LOVE_PROPENSITY)[type];
  if (this->temporary_trait_changes != NULL) {
    uVar1 += (&this->temporary_trait_changes->LOVE_PROPENSITY)[type];
    if ((short)uVar1 < 0) {
      uVar1 = 0;
    }
    else {
      if (100 < (short)uVar1) {
        uVar1 = 100;
      }
    }
  }
  iVar3 = 0;
  if (0 < rolls) {
    do {
      if ((int)(short)uVar1 + 1U < 2) {
        uVar2 = 0;
      }
      else {
        uVar2 = mt_trandom();
        uVar2 = (uVar2 % 0x7fffffff) /
                ((int)(0x7fffffff / (ulonglong)((int)(short)uVar1 + 1U)) + 1U);
      }
      iVar3 += uVar2;
      rolls += -1;
    } while (0 < rolls);
  }
  return iVar3;
}
The actual trait checks are random, but during worldgen they will be under the influence of one of the worldgen seeds (probably the History one) so they'll still be consistent.

I should note that all of these functions started out with names like "FUN_140910ae0" and "FUN_140910b50" - it was only through manual analysis that the types of all the different function parameters were identified (typically by starting from code where the data types can be trivially identified, and then tracing outwards from there) and meaningful names could be assigned to the functions themselves.

It also greatly helps that a small part of the source code for the Linux version is available (the "g_src" directory, which mainly only contains the code for rendering graphics and handling keyboard/mouse input).

Pages: 1 ... 4 5 [6] 7 8 ... 560