Covering Melee Corners
Posted: 2012-05-02 Filed under: Coding, General Leave a commentTraditional PnP tactical cover rules have some gray areas when it comes to complex 3-dimensional topography and large creatures. Mostly these are swept under the generalizations from the “flatness” of tradition PnP play. However, the Ikosa Framework must calculate cover within predictable constraints and more highly variable conditions.
For instance, melee cover (which can only occur when attacking into an adjacent cell) generally requires all “corners” of the source cell to have unhindered line of effect to the target cell. Assuming an attacking creature stands on a block of solid ground 5 foot higher than an adjacent target creature (such that the target creature is “diagonally-down” from the attacker), then lines from the back of the attacker must be blocked by the solid ground to attack the target; in exactly the same way as when attacking around a corner. It is unlikely that a game-master would rule the lower target had cover from the attacker standing on a higher platform, especially since attacking from higher ground typically gives a +1 to attack.
The Ikosa Framework has strategies to deal with this situation (and some processing optimizations).
Optimization first: When calculating cover (melee or reach/ranged) Ikosa must check lines between “corners” of the source (cell or point) and target (cell or cells) for terrain blockage or cover inducing effects in the cells being traversed by the lines.
To reduce processing, Ikosa only examines points that will reach from source to target without going through the source or target (thus culling certain points from consideration). This can be determined by looking at the relative integer cell coordinates between source and target cells to determine which faces are exposed to each other. When two cells are face to face, 4 points from the source and 4 points from the target are considered. When edge to edge, 6 and 6, and when corner to corner, 7 points each. Also, for reach/ranged attacks, there are additional target points possible (since for larger creatures the entire creature is being targeted, which spans many cells), but also additional culling (so that only points exposed to the source point) are considered.
For the downward attack mentioned above, Ikosa detects the gravity direction of the attacker and whether the terrain supports the attacker (thus creatures in flight above the surface are excluded from this test) and then excludes those faces from consideration if they would otherwise be needed. As a result, only attacker points that face-outward toward the target on the non gravitationally bound attacker face are used. In this case, only 4 points are considered (if the target is adjacent and down) or 6 (if target is diagonal and down).
If the attacker were in a cell 5 feet lower, however, the gravitationally bound face isn’t facing the target anyway, and since the all the target’s points are still usable, the higher target would have cover.
The Past Week
Posted: 2012-04-23 Filed under: Coding, Debugging, General Leave a commentOpportunistic attacks are now working fairly well. I’ve managed to trigger them off on movement from a threatened cube and by trying to use a ranged weapon in a threatened cube. Also tested: not being able to make an opportunistic attack if the target has cover, and only being able to attack when wielding a weapon that can make such an attack. Haven’t played with reach weapons yet.
I also discovered (and fixed) a problem with some of the attack handlers, in that I had a handler chain defined for a base class (AttackData) that prevented the chains for more specific attack types (MeleeAttackData, ReachAttackData and RangedAttackData) from activating. I ended up changing the interaction handler chain matching algorithm to work with exact type matches, rather than IsAssignableFrom(). Had to also make sure I wasn’t orphaning any use cases.
Lastly (and I still have to fix this), I discovered that a target standing on a low step could trigger a Cover alteration, resulting in a +4 to Armor Rating for the target. This is because the cubic region’s lower corners are blocked by the solid material of the cell. I’m going to look into using adjusted coordinates for determining extents for a target (rather than blindly using the cube corners) based on the IPhysical properties and intra-locator positioning (including Offsets)…and I’m going to put some stuff in to account for low barriers (2′ high or less) by trying some alternate point testing under “certain” conditions.
Model View View-Model
Posted: 2012-04-16 Filed under: BattleScape, Coding, General Leave a commentFinally got (most) of the client-side features back together under a more MVVM-like pattern (still haven’t adopted the RelayCommand style yet…). Now, I can more easily get additional data into the Opportunistic Inquiry Prerequisite dialog, since I won’t have to climb through data contexts and control-bound properties to find the data from the framework. I can just bind it in…
I also inched the “bio” part of my Kickstarter project a little bit farther. Every day I see more and more games on Kickstarter, quite a few of which are sandbox and adventure games. There’s an upside and a downside to that, the downside is in launching my project too late (which is comical to me as I “launched” about 7 years ago with the code, or 30+ years ago with the concept), and getting lost in the sea of games. The upside is that the project funds sought looks like they are realistic to keep the developers eating (which is a requirement of mine as well), without having to work in a factory.
Model View Something…
Posted: 2012-04-09 Filed under: Coding, General Leave a commentI started the client UI (and proxy code) for the Ikosa Framework quite some time ago. Since the whole framework has been under development since early 2006 (six years) the client UI is probably no younger than about early 2007 (I could look it up in my Vol 1 or 2 of my notebooks if I had the inclination).
Anyway, WPF hit the scene with .NET 3 in late 2006, so I was working in unexplored territory (with my mental models at least, if not in accepted “best practices”). Correspondingly, much of the client-side framework was (and still is) fairly hodgepodge. I slowly came around to RoutedCommands (fantastic things), and DataTemplates (and DataTemplateSelectors!), and some data-binding.
Mainly what held me back from pervasive data-binding was that most of the instances I had to visualize were coming from the proxies as DataContracts. These were not implementing INotifyPropertyChanged, or INotifyCollectionChanged, and it wasn’t obvious (in my bone-headed way) how to make this “work” with a data-model controlled on the other end of the WPF channel. I may also have been reluctant to wrap data-contract classes (yet again) for WPF, since I already had to pack and unpack them in the host-side for processing in the Ikosa setting.
However, once I got around to the opportunistic attack prerequisite, I saw that to visualize the options well, I needed to provide useful information from elsewhere in my data “model”, which could be “found” scattered in a loose-confederation of DataContexts, POCO properties (set via constructor or assigned after an event fired) and some DependencyProperties mostly all parked on various controls of the UI, some templated, some not.
Then I decided to change all that…(or most of it)…over Easter Weekend, while also trying to assist two black belts testing for second degree next weekend, driving back and forth to Reading, PA twice (about 5 hours total), and having a rather pleasant Easter at my parents.
So far, I have a stable build. But am seeing that I’ll have to deal with some ObservableCollections that I (now) understand won’t work across threads. And I have some server-side debugging to do (I also altered the hosting model to allow a single user to control multiple actors, in theory). What I have started as a MVVM, but I started adding more “C” (as in Controller) type functions, since I was moving them off of the UI controls where they were before.
All in all, despite the fact I broke my system (client and host), I am satisfied that the foundation is becoming better.
Face? Book?
Posted: 2012-04-03 Filed under: General Leave a commentFinally became a part of the Facebook nation. Mainly to help with proving to people who may eventually pledge on Kickstarter that I am real.
Semi-Automatic Attacks
Posted: 2012-04-02 Filed under: General Leave a commentReworked some of the GetTargets() code in the host when unpacking attack aim targets from the client. Given that a melee attack provides a target cell, I was able to automatically select a target if no explicit target ID was given. (I still have to work the code to “randomly” pick a target if two targets are in the same cell, but that’s a minor detail). This makes automatic melee attacks much easier to perform, as the client no longer has to select the target in order to make a melee attack.
I also got automatic ranged attacks up and working (but the client must select a target, since ranged attacks are not typically into the adjacent cell). I had to fix some things with the critical damage multiplier for projectiles/ammunition, but all should be good now.
Even though opportunistic attacks have been on my “tactical radar” for awhile now. They are now the next thing to tackle directly.
Theme Music and Sprites
Posted: 2012-03-29 Filed under: General, Guildsmanship Leave a commentI got to hear the first few measures of the Ikosa Theme that my daughter has been working on. Sounds pretty cool, with a low bass line that rolls along (kind of like Interplay’s Descent). It makes me want to cobble together a “arcade-cabinet-mode” version of the host and client.
Haven’t seen the images my pixel master has been (sort-of) working on. He’s a busy teen boy; mostly busy with playing online games. Hopefully I can get him to produce some images for the toolbars (and ribbon) to replace the rotated text I have in the toolbars currently.
Keeping Threads Untangled (Server-Side)
Posted: 2012-03-22 Filed under: General Leave a commentWCF, WPF, and TPL. Three programming APIs with thread issues. Getting them to work together across multiple application domains with shared state and callback has its challenges.
First of all, the framework currently is spread across three services, each with its own WCF CallbackContract: LoginService, VisualizationService and IkosaService. By using callback contracts, I skirt around forcing clients to ping-poll to see if anything new is ready. I also went with Net.TCP connections, allowing duplex channels without having to muck about with port forwarding on home firewalls.
Currently, I work under a known service pattern, with each service at its own fixed endpoint servicing all requests. Therefore, I have a [ServiceBehavior] attribute that specified ConcurrencyMode.Multiple, InstanceContextMode.Single, and UseSynchronizationContext=false. I made the class use static members, limiting me to one per application domain (may change this in the future, but not pressed to do it at the moment).
What these ServiceBehaviors do:
– ConcurrencyMode.Multiple: multiple threads are allowed in, and I handle thread synchronization
– InstanceContextMode.Single: basically means the service is a shared singleton
– UseSynchronizationContext=false: if I didn’t do this, inbound processing requests would get queued into the main UI’s thread, causing contention with the UI
These concurrent, unsynchronized singleton services need strategies to handle read and update collisions of their shared state. I have tended to favor ReaderWriterLockSlim in the past, but have also delved into TPL concurrent collections for some of the basic list management and notification queues. This works well with classifying service calls as lock-free, requires-read-lock, or write-blocking (and the occasional upgradeable-read-lock).
When probing the shared Ikosa state (or packaged resources) I shift into ReaderWriterLockSlim mode; when dealing with pure client-server stuff (such as managing the list of potential callback candidates), I tend to rely on the concurrent collections like the ConcurrentDictionary, and get to run without locking the ReaderWriterLockSlim stuff.
One last thing on the server-side is providing feedback from the largely free-threaded servicing hosts back to the host UI. Since calls to WPF UI needs to be dispatched, I provide an Action delegate to each service they can use to call-back. When I assign the delegate in the host, I need to use a Dispatcher.Invoke(), but I also need to wrap that in an Task.Factory.StartNew(), so that the feedback doesn’t get blocked by whatever the UI is doing, and can serviced when the UI thread gets around to servicing messages again.
Task.Factory.StartNew((msg) =>
this.Dispatcher.Invoke((Action)((msg) =>
{
// TODO: do stuff with msg
})));
Well, next I’ll give a brief view of the client threading considerations.
Pixel Master
Posted: 2012-03-20 Filed under: General Leave a commentI started tapping my son to generate some images for game items and UI elements. He’s getting into it, so hopefully the demo application will look a little less like a no-frills business app, and a little bit more like a game.
I’m also planning on implementing a hotkey for a regular attack action with whatever weapon is in the actor’s main hand. This will allow combat between two fighters a lot easier, especially if I automate the dice rolls for attack and critical confirmation.
Three’s Company
Posted: 2012-03-14 Filed under: Coding, Debugging, General Leave a commentIn order to really test delaying on one’s turn, I had to add another character to the setting. Red Dude, Blue Dude, and now Green (I forgot to include the last name of Dude). I need to run three clients to test them out. Eventually I’ll make a multi-character client for TB2.
Anyhow…I did find that although I had most of the code to manage the delay list and remove actors from it when they act, I hadn’t added anything to put them into the list when they delay for the first time.
So, I sorted that all out now; and exposed some client-state refresh issues.
Therefore: next up…better signalling from the host to the clients when the delay step is activated. When the DelayTickStep is the current step, the game clock doesn’t tick unless the delaying actor decides to act. Therefore, one of the normal update signals (time-tick) isn’t sent to the clients, like it is during a LocalTickStep or LocalTimeStep.
I also need some better visual cues in the client that they can or cannot act, based on who has the focused budget.
While I’m at it, I might as well get some character models with different colors. I have some…but they’re not dimensioned to work with the auto-scaling features of the creature sizer; yet I should be able to throw a Scale3DTransform around them in the XAML.
