Saturday, December 27, 2025

The Fantasy Trip on a spaceship

I figured I'd try a bit of solo TFT Zombicide style gaming and set up one of spaceship deck posters. Put in a few random goals and my small pair of adventurers find themselves in the bridge of a spaceship. How they got there, and why an Elf and a Centaur are now in a science fiction setting is simply the joy of gaming.

I also added in the OSE rule that every 2 turns roll to see if something spawns. I added a roll also when any combat was happening as fights are noisy and bound to bring in other critters that may want fresh food. I also decided to use the entire stack of creature cards I have from all the things - there must be a couple hundred by now. Basically, an encounter happens and I'd roll some dice to narrow down the deck. Oddly did not even know about the kingowing from the bestiary (which, wow, sells for $80!) but it showed up.

I lost pretty quickly - 2 adventurers is not really enough, much like most RPG game or Zombicide. But at least I got to play with some toys. 

the initial set up, with tentacles at the exit

started on the bridge. I assume the red alert klaxons are sounding!

a spider! Unfortunately, in TFT Elves are at a -3 DX against spiders and the like. Fortunately, it cannot fit up the stairwell.


Unfortunately, the smaller ones can!

And here's the kingowing that killed them - the Centaur was busy trying to get ants off of his hide and while the Elf almost killed the beast, the beast killed him first.

It took longer to set up than actually play but that's okay - it was fun to mix a few genres together. It was pretty random - I suppose I really should formalize a few more rules like I did with our initial run. More of an experiment in solo gaming I suppose. Though without the interaction and decisions from other players it is not as much fun. I did randomize which adventurer creatures would attack, with a bias towards those inflicting damage.

Funny thing was I shared some pics with my game group and he said of course the spider was mad, its bathtime with its rubber ducky got interrupted. Oddly enough...
one of these days I'll finish painting the tub
and a closeup of the creature at the end. Which I did mostly finish painting. Finally. See - I can make progress against the plastic pile o'shame!
eeks!
Taking a bit of a break from the Traveller software - despite being a holiday week I was on call, and we only get Christmas Day itself off. And since I was on call it was still a bit stressful. And even got a few alerts today, so worked a bit as well. I keep telling myself I only have to hold on 3 more years or so! And at my age, that goes by awfully fast. But then I worry about too much unstructured time - I am not good with that either. I've 3.25 years to figure that out. I'll probably volunteer at an animal shelter and probably work part-time. I've got plans for what I need to do for work, and there is no way to get it down in 3 years. Assuming I am still with this company and still alive! I'd better be - I did the lifetime membership at my new gym, and the breakeven point is oddly at the time of my potential retirement!

And finally, January is coming up fast. Not sure if I'll do the character challenge again this year. I may but as always, I'll have to see about stockpiling some ahead of time as sadly my days are pretty busy. And when they are not busy, I often just don't have the mojo it seems. The holidays, though I do enjoy them, are also more stressful to me than they should be for a number of generally self-imposed reasons. Self-awareness is not always what it is cracked up to be!

Saturday, December 20, 2025

Traveller System Update 27 - adding empty orbits

After getting all the issues with the updates to .NET 10, and adding the captured & empty orbits table, I went ahead and added the function to get the empty orbits. Which is just a count of the empty orbits I think, so will need to figure out by reading the book how you place the empty orbits. We know that the main world, if the system is generated from a main world, is in the habitable zone. Though I also need to check to see if that is the case for the main world when a planetoid belt, such as Glisten.

Anyway - I got that working with one logic flaw I need to correct. But also realized I probably should extend my die roll method. What I currently do is find the min and max die rolls and roll on that. Some tables are 2d6 in the book, some are 1d6. I am passing in the number of dice to roll for the various tables, but now wondering if we really want to make this even more flexible, do we want to add the number and type of dice to the tables? Of course, then it is not Traveller in my head, so that may be a step too far.

But: the die rolls have to be within the range of values that the user has given (and I really need to make sure there are no duplicate rolls as well when adding to the tables. But that is another thing to worry about later). Anyway - we do not want a die roll outside the range in the table. While Book 6 has a range of 1 through 6 for the captured planets and empty orbits, what if someone wants a smaller, or a larger, range? Currently I get the lowest and highest die rolls and adjust the results from the die roll to fit the range. Now I am repeating this code in a lot of places. The fix is to pass in the minimum and maximum ranges in the die roll function itself so I don't have to repeat that code.

The current code for empty orbits:

 private async Task<int> findEmptyOrbits()

 {

     int results = 0;

     List<TCapturedAndEmpty?> capturedAndEmpty = await _capturedAndEmptyRepository.GetAll();

     if (capturedAndEmpty == null || capturedAndEmpty.Count == 0) { return results; }

     int minD6 = capturedAndEmpty.Min(c => c != null ? c.DieRoll : 0);

     int maxD6 = capturedAndEmpty.Max(c => c != null ? c.DieRoll : 0);

     if (minD6 == 0 && maxD6 == 0) { return results; }

     int d6 = _utility.DieRoll(maxD6, 1);

     if (d6 < minD6) { d6 = minD6; }

     TCapturedAndEmpty? match = capturedAndEmpty.FirstOrDefault(c => c != null && c.DieRoll == d6);

     if (match == null || !match.EmptyOrbits) { return results;};

     // we have empty orbits; how many?

     d6 = _utility.DieRoll(maxD6, 1);

     if (d6 < minD6) { d6 = minD6; }

     return capturedAndEmpty.First(c => c != null && c.DieRoll == d6)?.EmptyOrbitsQty ?? 0;

 }


You can see where I am getting the min and max range based on the loaded table. Thinking the check for min and max will be moved to the utility.DieRoll function, so we have something like utilityDieRoll(numberOfSides, numberOfDice, minRange, maxRange). and then do the "if results < minRange results = minRange" sort of thing.

Anyway - one may wonder why I am doing this the way I am. As there are a lot of Traveller system generators out there. But most of them do not allow you to set the tables yourself. And while most people probably won't want to anyway, it is the way my mind works and how I've always approached software. Let the user have more control over things. This system is basically a giant software settings thing in a way: you can set all the tables up how you want. Will it ever get used? Very doubtful, but regardless, it is something I want to do, and it is usually pretty fun.

And let's see, I need a picture.

The ill-fated Blacklist Games Fantasy Figures 2 project, though bringing in a LOT of money, failed horribly. The assets got bought out a bit ago by Wildspire Minis. I've backed a few of their projects as they make good cheap minis. They offered the backers of that Kickstarter a reduced rate for the minis. Yes, that we already paid for several years (years!) ago. But even with the additional cost, the price per mini is still really cheap. And there are some interesting ones in there, such as this Cthulhu demon thing. And a hippogryph. So the one I finally got around to painting can have a friend! Bag and bags of minis I need to paint. To go with the boxes and boxes of minis I need to paint.

Sunday, December 14, 2025

Zombicide:Invader - we actually won

It was a Zombicide:Invader Sunday morning (well, that and I made sticky rolls since Nate was coming over. Else I'd have eaten the entire batch and become sick. My weakness is baked goods. And you may have noted I like to bake!)

Anyway, we rummaged through the online missions and decided to try this one: https://cdn.svc.asmodee.net/production-zombicide/uploads/dl/Mission_M29_A_New_Danger.pdf It is nice that there on-line and additional missions. I backed that KS years ago and have the civilians expansion, so we have a lot of options for characters. Though I've misplaced a few of those minis as I sometimes paint them for playing in another game, and they do not always get back to their box. My lack of organization shows up in places like that.

Though as per my other gaming group, we ended talking the first hour as it has been a while since we've seen each other. Fortunately, I started the set-up before he showed up, so we still managed to play and finish by about 12:30. We thought we were goners twice as we ended up having 2 abominations in the same room as us! Fortunately, Invaders characters have a bit more armor than other versions, so we took a bit of a beating. But I managed to roll well a few times and managed to take out the abominations with a sledgehammer. And the only reason for that is that Invaders allows for concentrated fire so all the damage can be applied to a single target. Which also explains why those abominations are more likely to show up: they are a bit easier to defeat.

Despite 3 characters 1 point away from death, we actually won. We had hard cards in the spawning at the beginning, but the last turn or two got lucky and managed to actually get away with all the stuff we needed. High fives all around!

we never did fire the big gun!

we thought we were doomed

not looking good!

rolls going in the oven!
I did some library updates for the Traveller software, as there have been a few point releases. Meaning something like version 10.0 to 10.1. Nothing earth-shattering and no new code, so no new update notes. I also found that Microsoft has simplified the solution file. While interestingly enough I can edit the same code in a different editor on the Mac, the IDE Microsoft wrote, and I've used since 1.0 basically, has a solution file that I've never really bothered with. But it has a bunch of GUIDs and stuff that for large projects become a nightmare sometimes. Now it is a lot simpler! Not that anyone reading this really cares but here are the before and after views of the solution file for the Traveller project, which is a tiny thing in the world of software.

Old:
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TravSystem", "TravSystem.csproj", "{8FA7BA1A-44C3-A632-3C25-2817CC365197}"
EndProject
Global
       GlobalSection(SolutionConfigurationPlatforms) = preSolution
               Debug|Any CPU = Debug|Any CPU
               Release|Any CPU = Release|Any CPU
       EndGlobalSection
       GlobalSection(ProjectConfigurationPlatforms) = postSolution
               {8FA7BA1A-44C3-A632-3C25-2817CC365197}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
               {8FA7BA1A-44C3-A632-3C25-2817CC365197}.Debug|Any CPU.Build.0 = Debug|Any CPU
               {8FA7BA1A-44C3-A632-3C25-2817CC365197}.Release|Any CPU.ActiveCfg = Release|Any CPU
               {8FA7BA1A-44C3-A632-3C25-2817CC365197}.Release|Any CPU.Build.0 = Release|Any CPU
       EndGlobalSection
       GlobalSection(SolutionProperties) = preSolution
               HideSolutionNode = FALSE
       EndGlobalSection
       GlobalSection(ExtensibilityGlobals) = postSolution
               SolutionGuid = {7B8C67AC-AD43-4E4F-8452-D444DABD3509}
       EndGlobalSection
EndGlobal

New:
<Solution>
  <Project Path="TravSystem.csproj" />
</Solution>

I prefer the new :)



Saturday, December 06, 2025

Traveller System Update 26 - Figured out the migration issue

It took a bit but basically had to get the most current version of various code things. Bleeding edge is not for production use, but great for personal projects. But - I got the migration to get created but then it broke doing the actual migration. I gave it a few days and got back to it today and found two things. For SQLite (the DB in use, which I think I've mentioned has a really interesting history), the .NET 10 adds a lock table. Since I stopped processing the DB without letting the framework clear that lock, once I figured out the other part, the application just froze, waiting for that lock file. Deleting it works fine. The other thing I found was that because the migration process checks across all models, it saw some foreign key references in other models so added indices to help speed things up when reading data. Unfortunately, those are optional related records so the keys may be null. As this database is so tiny indexing really does not matter a great deal, I just commented those out.

I do need to correct the titles, but now we have the captured and empty planets table. I'll note that though I am copying the data from Book 6, there is no reason to do so and the way I look up the tables if it is a random die roll is to get the minimum and maximum die and roll on that. If you want a d4 table, it will work. A d20 table, it will work. Though now that I type that, I will have to verify if you've skipped a die that we go up to the next available one or something.


I'll also note that I actually switched to a fiber internet connection, though the coax is still attached as well. But I can get the same speed but symmetrical (download and upload about the same speed) for less than half of what I was paying. When I went to disconnect my previous service, they suddenly found they could undercut the price, and I could pay even less (but lacking symmetrical speeds as coax does not work the same as fiber). In theory I could have kept both services and still paid less than I did, but as I am not a data center I really do not need that level of redundancy. Anyway, I now have a 2nd connection, which 2 weeks later they finally buried the cable. And I can unwrap that coax that wraps around my basement as the terminal is at the opposite side of the basement as my office space is. The install guy put the box right outside so there is only about q 10' cable between where it comes in. But the old cable is still there, and who knows, they may try to get me back for even less. Competition is a good thing!

Plus, I had to move the not-used-in-10-years treadmill so the installation tech could get access to that area. It is now in the garage. I've added a shelf where the treadmill was, and so a chunk of my Lego that I really do plan on selling is now off the floor. Next step is to take that treadmill either to the used sports place or the dump. We did use it a lot back when we were running marathons. And yes, I did run marathons, my wife has actually run 50 miles. She is crazy (a requirement being married to me!

So perhaps tomorrow I'll clean up the titles and continue on with the system creation. I can run it for my new title :)