2020. március 19., csütörtök

Exploring Monster Taming Mechanics In Final Fantasy XIII-2: Data Validation And Database Import

Continuing on with this miniseries of exploring the monster taming mechanics of Final Fantasy XIII-2, it's time to start building the database and populating it with the data that we collected from the short script that we wrote in the last article. The database will be part of a Ruby on Rails project, so we'll use the default SQLite3 development database. Before we can populate the database and start building the website around it, we need to make sure the data we parsed out of the FAQ is all okay with no typos or other corruption, meaning we need to validate our data. Once we do that, we can export it to a .csv file, start a new Rails project, and import the data into the database.


Validating a Collection of Data

Considering that we parsed out 164 monsters with dozens of properties each from the FAQ, we don't want to manually check all of that data to make sure every property that should be a number is a number and all property names are correctly spelled. That exercise would be way too tedious and error prone. This problem of validating the data sounds like it needs an extension to our script. Since we have the data in a list of hash tables, it should be fairly straightforward to create another hash table that can be used to validate each table in the list. The idea with this hash table is to have a set of valid properties as the keys in the table, and the values are regexes that should match each property value that they represent. These regexes will be more specific to each property, since those properties have already matched on the more general regexes that were used to collect the data in the first place. Additionally, every key in each monster hash should be in this template hash, and every template hash key should be in each monster hash. We could get even more detailed with our checks, but this validation should be enough to give us confidence in the data.

To get started, we'll build up the first couple entries in the template hash and write the validation loop. Once it's working, we can fill out the rest of the entries more easily. Here are the name and minimum base HP entries along with the validation loop:
PROPER_NAME_REGEX = /^\w[\w\s]*\w$/
NUMBER_REGEX = /^\d+(:?,\d{3})?$/

VALID_MONSTER = {
"Name" => PROPER_NAME_REGEX,
"Minimum Base HP" => NUMBER_REGEX
}

data.each do |monster|
VALID_MONSTER.each do |key, regex|
if monster.key?(key)
unless monster[key] =~ regex
puts "Monster #{monster["Name"]} has invalid property #{key}: #{monster[key]}."
end
else
puts "Monster #{monster["Name"]} has missing property #{key}."
end
end

monster.each do |key, value|
unless VALID_MONSTER.key?(key)
puts "Monster #{monster["Name"]} has extra property #{key}: #{value}."
end
end
end
This is a fair amount of code, so let's take it in parts. First, we define two regexes for a proper name and a number. The proper name regex is the same as part of our previous property value regex in that it matches on multiple words separated by whitespace, but it has two extra symbols at the beginning and end. The '^' at the beginning means that the next character in the pattern has to appear at the start of the string, and the '$' at the end means that the last character that matches has to be at the end of the string. Together, these symbols mean that the entire string needs to match the regex pattern.

The number regex is similar to the proper name regex, except that it matches on numbers instead of words. The (:?,\d{3}) group matches on a comma followed by three digits because the {3} pattern means that the previous character type, in this case a digit, must be repeated three times. This group is optional, so the regex will match on 1234 as well as 1,234. The number regex is also wrapped in a '^' and a '$' so that the entire string must match the pattern.

The next constant is simply the start of our monster template hash with "Name" and "Minimum Base HP" entries. What follows is the validation loop, and it is laid out about how it was described. First, we iterate through each monster in the data list that we have already populated with the monsters from the FAQ. Within each monster we iterate through every entry of the valid monster template. If the monster has the property we're looking at, we check if the property value matches the regex for that property. If it doesn't, we print out an error. If the property doesn't exist, we print out a different error. Then we iterate through every property of the monster, and if a property doesn't exist in the template, we print out another error.

If we run this script now, we end up with a ton of errors for extra properties because we haven't added those properties to the template, yet. However, from looking at the first few monster's outputs, it appears that the other checks are working, so we can start filling out the rest of our template. We can quickly add in the obvious properties, checking the script periodically to make sure we haven't gone astray. The mostly finished template looks like this:
PROPER_NAME_REGEX = /^\w.*[\w)!%]$/
NUMBER_REGEX = /^\d+(:?,\d{3})?$/
SMALL_NUMBER_REGEX = /^(\d\d?\d?|N\/A)$/
PERCENTAGE_REGEX = /^(\d\d?\d?%|N\/A)$/
LIST_REGEX = /^((:?All )?\w+(:?, (:?All )?\w+)*|N\/A)$/
FREE_TEXT_REGEX = /^\S+(?:\s\S+)*$/
TIME_REGEX = /^\d\d?:\d\d$/

VALID_MONSTER = {
"Name" => PROPER_NAME_REGEX,
"Role" => PROPER_NAME_REGEX,
"Location" => PROPER_NAME_REGEX,
"Location2" => PROPER_NAME_REGEX,
"Location3" => PROPER_NAME_REGEX,
"Max Level" => SMALL_NUMBER_REGEX,
"Speed" => SMALL_NUMBER_REGEX,
"Tame Rate" => PERCENTAGE_REGEX,
"Minimum Base HP" => NUMBER_REGEX,
"Maximum Base HP" => NUMBER_REGEX,
"Minimum Base Strength" => SMALL_NUMBER_REGEX,
"Maximum Base Strength" => SMALL_NUMBER_REGEX,
"Minimum Base Magic" => SMALL_NUMBER_REGEX,
"Maximum Base Magic" => SMALL_NUMBER_REGEX,
"Growth" => PROPER_NAME_REGEX,
"Immune" => LIST_REGEX,
"Resistant" => LIST_REGEX,
"Halved" => LIST_REGEX,
"Weak" => LIST_REGEX,
"Constellation" => PROPER_NAME_REGEX,
"Feral Link" => PROPER_NAME_REGEX,
"Description" => FREE_TEXT_REGEX,
"Type" => PROPER_NAME_REGEX,
"Effect" => FREE_TEXT_REGEX,
"Damage Modifier" => FREE_TEXT_REGEX,
"Charge Time" => TIME_REGEX,
"PS3 Combo" => FREE_TEXT_REGEX,
"Xbox 360 Combo" => FREE_TEXT_REGEX,
"Default Passive" => PROPER_NAME_REGEX,
"Default Skill" => PROPER_NAME_REGEX,
"Special Notes" => FREE_TEXT_REGEX,
}
Notice that the PROPER_NAME_REGEX pattern had to be relaxed to match on almost anything, as long as it starts with a letter and ends with a letter, ')', '!', or '%'. This compromise had to be made for skill names like "Strength +10%" or constellation names like "Flan (L)" or feral link names like "Items Please!" While these idiosyncrasies are annoying, the alternative is to make much more specific and complicated regexes. In most cases going to that extreme isn't worth it because the names that are being checked will be compared against names in other tables that we don't have, yet. Those data validation checks can be done later during data import when we have the other tables to check against. Waiting and comparing against other data reduces the risk that we introduce more errors from making the more complicated regexes, and we save time and effort as well.

The location property has an odd feature that makes it a bit difficult to handle. Some monsters appear in up to three different areas in the game, but it's only a handful of monsters that do this. Having multiple locations combined in the same property is less than ideal because we'll likely want to look up monsters by location in the database, and we'll want to index that field so each location value should be a unique name, not a list. Additionally, the FAQ puts each location on a separate line, but not prefixed with the "Location-----:" property name. This format causes problems for our script. To solve both problems at once, we can add "Location2" and "Location3" properties anywhere that a monster has a second or third location by directly editing the FAQ.

This template covers nearly all of the monster properties, except for the level skill and passive properties. We'll get to those properties in a second, but first we have another problem to fix. It turns out that the two location properties we added and the last three properties in the template don't always occur, so we have to modify our check on those properties slightly:
# ...
elsif !["Location2", "Location3", "Default Passive", "Default Skill", "Special Notes"].include? key
puts "Monster #{monster["Name"]} has missing property #{key}."
end
# ...
We simply change the else branch of the loop that checks that all properties in the template are in the monster data so that it's an elsif branch that only executes if the key is not one of those optional keys.

Now we're ready to tackle the level properties. What we don't want to do here is list every single level from 1 to 99 for both skill and passive properties. There has to be a better way! The easiest thing to do is add a check for if the key matches the pattern of "Lv. XX (Skill|Passive)" in the loop that checks if each monster property exists in the template, and accept it if the key matches and the value matches the PROPER_NAME_REGEX. This fix is shown in the following code:
LEVEL_PROP_REGEX = /^Lv\. \d\d (Skill|Passive)$/
# ...
monster.each do |key, value|
unless VALID_MONSTER.key?(key)
if key =~ LEVEL_PROP_REGEX
unless value =~ PROPER_NAME_REGEX
puts "Monster #{monster["Name"]} has invalid level property #{key}: #{value}."
end
else
puts "Monster #{monster["Name"]} has extra property #{key}: #{value}."
end
end
end
# ...
I tried to make the conditional logic as simple and self-explanatory as possible. I find that simpler is better when it comes to logic because it's easy to make mistakes and let erroneous edge cases through. If this logic was any more complicated, I would break it out into named functions to make the intent clearer still.

With this addition to the data validation checks, we've significantly reduced the list of errors from the script output, and we can actually see some real typos that were in the FAQ. The most common typo was using "Lvl." instead of "Lv." and there are other assorted typos to deal with. We don't want to change the regexes to accept these typos because then they'll appear in the database, and we don't want to add code to the script to fix various random typos because that's just tedious nonsense. It's best to fix the typos in the FAQ and rerun the script. It's not too bad a task for these few mistakes.

Exporting Monsters to a CSV File

Now that we have this nice data set of all of the monster properties we could ever want, we need to write it out to a .csv file so that we can then import it into the database. This is going to be some super complicated code. Are you ready? Here it goes:
require 'csv'
opts = {headers: data.reduce(&:merge).keys, write_headers: true}
CSV.open("monsters.csv", "wb", opts) do |csv|
data.each { |hash| csv << hash }
end
Honestly, Ruby is one of my favorite languages. Things that you would think are complicated can be accomplished with ease. Because we already structured our data in a csv-friendly way as an array of hashes, all we have to do is run through each hash and write it out through the CSV::Writer with the '<<' operator.

We need to take care to enumerate all of the header names that we want in the .csv file, and that happens in the options that are passed to CSV.open. Specifically, headers: data.reduce(&:merge).keys tells the CSV::Writer what the list of header names is, and the writer is smart enough to put blank entries in wherever a particular header name is missing in the hash that it is currently writing out to the file. The way that code works to generate a list of header names is pretty slick, too. We simply tell the data array to use the Hash#merge function to combine all of the hashes into one hash that contains all of the keys. Since we don't care about the values that got merged in the process, we simply grab the keys from this merged hash, and voila, we have our headers.

The .csv file that's generated from this script is a real beast, with 204 unique columns for our 164 monsters. Most of those columns are the sparsely populated level-specific skills and passive abilities. We'll have to find ways to deal with this sparsely populated matrix when using the database, but it should be much better than dealing with one or two fields of long lists of abilities. At least, that's what I've read in books on database design. I'm learning here, so we'll see how this goes in practice.

Importing Monsters Into a Database

This part isn't going to be quite as easy as exporting because we'll need to write a database schema, but it shouldn't be too bad. Before we get to that, we need to create a new Ruby on Rails project. I'll assume Ruby 2.5.0 or higher and Rails 6.0 are installed. If not, see the start of this Rails Getting Started guide to get that set up. We start a new Rails project by going to the directory where we want to create it and using this Rails command:
$ rails new ffxiii2_monster_taming
Rails generates the new project and a bunch of directories and files. Next, we descend into the new project and create a new model for monsters:
$ cd ffxiii2_monster_taming
$ rails generate model Monster name:string
In Rails model names are singular, hence "Monster" instead of "Monsters." We also include the first database attribute that will be a part of the migration that is generated with this command. We could list out all 204 attributes in the command along with their data types, but that would be terribly tedious. There's an easier way to get them into the migration, which starts out with this code to create the Monster table:
class CreateMonsters < ActiveRecord::Migration[6.0]
def change
create_table :monsters do |t|
t.string :name

t.timestamps
end
end
end
All we have to do is add the other 203 attributes along with their data types and we'll have a complete table ready to generate, but how do we do this efficiently? Conveniently, we already have a list of the attribute names as the header line in the monsters.csv file. We just have to copy that line into another file and do some search-and-replace operations on it to get the list into a form that can be used as the code in this migration file.

First, we'll want to make a couple changes in place so that the .csv header has the same names as the database attributes. This will make life easier when we import. All spaces should be replaced with underscores, and the periods in the "Lv." names should be removed. Finally, the whole line should be converted to lowercase to adhere to Rails conventions for attribute names. Once that's done, we can copy the header line to a new file, replace every comma with a newline character, and replace each beginning of a line with "      t.string " to add in the attribute types. They are almost all going to be strings, and it's simple to go back and change the few that are not to integers, floats, and times. I did this all in Vim, but any decent text editor should be up to the task. Now we have a complete migration file:
class CreateMonsters < ActiveRecord::Migration[6.0]
def change
create_table :monsters do |t|
t.string :name
t.string :role
t.string :location
t.string :location2
t.string :location3
t.integer :max_level
t.integer :speed
t.string :tame_rate
t.string :growth
t.string :immune
t.string :resistant
t.string :halved
t.string :weak
t.string :constellation
t.integer :minimum_base_hp
t.integer :maximum_base_hp
t.integer :minimum_base_strength
t.integer :maximum_base_strength
t.integer :minimum_base_magic
t.integer :maximum_base_magic
t.string :feral_link
t.string :description
t.string :monster_type
t.string :effect
t.float :damage_modifier
t.time :charge_time
t.string :ps3_combo
t.string :xbox_360_combo
t.string :default_passive
t.string :default_skill
t.string :special_notes
t.string :lv_02_passive
t.string :lv_02_skill
#...
# over a hundred more lv_xx attributes
#...
t.string :lv_99_passive
t.string :lv_99_skill

t.timestamps
end
end
end
Now, we can run this migration with the command:
$ rails db:migrate
And we have the beginnings of a monster table. We just need to populate it with our monsters. Rails 6.0 makes this task quite simple using a database seed file, and since we have the same names for the database attributes as the .csv file column headers, it's dead simple. In the lib/tasks/ directory, we can make a file called seed_monsters.rake with the following code:
require 'csv'

namespace :csv do

desc "Import Monster CSV Data"
task :import_monsters => :environment do

csv_file_path = 'db/monsters.csv'

CSV.foreach(csv_file_path, {headers: true}) do |row|
Model.create!(row.to_hash)
puts "#{row['name']} added!"
end
end
end
When we run this task, the code is going to loop through each line of the .csv file (that we make sure to put in db/monsters.csv), and create a monster in the database for each row in the file. We also print out the monster names so we can see it working. Then it's a simple matter of running this command:
$ rails db:seed
And we see all of the monster names printed out to the terminal, and the database is seeded with our 164 monsters.

We've accomplished a lot in this post with running some validation checks on the monster data, exporting it to a .csv file, creating a database table, and importing the monsters.csv file into that table. We still have plenty to do, creating and importing the other tables and relating the data between tables. That will be the goal for next time.

Podcast Episode 28 - Lessons Learned And Campaign Happenings


A lot of games over the past couple of weeks, and some lessons learned as a DM! Come listen as I share about running boss battles, using random events in interesting ways and how a big reveal had me worried that I'd lost a player!


Anchor Episode link: https://anchor.fm/the-dungeon-masters-handb/episodes/Episode-28---Lessons-Learned-and-Campaign-Happenings-easbbl

Leave me a voice message and let me know what you think or ask questions if you have them! (312) 625-8281‬ (US/Canada)

You can also leave a message on Anchor: anchor.fm/the-dungeon-masters-handbook/message 

Find episode posts and other D&D content on my blog: chgowiz-games.blogspot.com 

Intro music: Dragonaut by Bradley The Buyer (bit.ly/2ASpAlF)
Outro music: Dream by Wild Shores (bit.ly/2jbJehK)
Stinger music by TJ Drennon - Check out his Patreon page at https://www.patreon.com/TJD/!

2020. március 16., hétfő

Podcast Episode 27 - Horrors Under Tuluk - A Player's Journal


This is a VERY special episode and it's an experiment! David, player of Eadwig from my Etinerra campaign, submitted a fantastic adventurer's journal entry that I simply had to share. I've been listening to other spoken word/voice acting podcasts and thought I'd try my hand at reading the journal entry with some effects! I hope you enjoy it as much as I enjoyed creating it! Let me know what you think!



Anchor Episode link: https://anchor.fm/the-dungeon-masters-handbook/episodes/Episode-27---Horrors-Under-Tuluk---A-Players-Journal-eak8ko

Leave me a voice message and let me know what you think or ask questions if you have them! (312) 625-8281‬ (US/Canada)

You can also leave a message on Anchor: anchor.fm/the-dungeon-masters-handbook/message 

Find episode posts and other D&D content on my blog: chgowiz-games.blogspot.com 

Intro music: Dragonaut by Bradley The Buyer (bit.ly/2ASpAlF)
Outro music: Dream by Wild Shores (bit.ly/2jbJehK)

2020. március 5., csütörtök

People Behind The Meeples - Episode 207: Jeremiah Donaldson

Welcome to People Behind the Meeples, a series of interviews with indie game designers.  Here you'll find out more than you ever wanted to know about the people who make the best games that you may or may not have heard of before.  If you'd like to be featured, head over to http://gjjgames.blogspot.com/p/game-designer-interview-questionnaire.html and fill out the questionnaire! You can find all the interviews here: People Behind the Meeples. Support me on Patreon!


Name:Jeremiah Donaldson
Email:jerry@ephiroll.com
Location:London, Ky
Day Job:Was in call centers the last 5 years, but that's bad for my health and I'm in the process of switching things up.
Designing:Five to ten years.
Webpage:http://www.ephiroll.com
Blog:http://ephiroll.com/wordpress/
Facebook:Ephiroll Productions
YouTube:Jeremiah Donaldson
Other:https://ello.co/ephiroll
Find my games at:Everything is on Amazon, my card games are also on The Game Crafter, and my RPG stuff is on DriveThruRPG.
Today's Interview is with:

Jeremiah Donaldson
Interviewed on: 8/17/2019

Jeremiah Donaldson is a designer and author from London, but Kentucky, not the UK. He's written several sci-fi and horror stories and designs games set in the worlds he's created for those stories. Read on to learn more about Jeremiah and the projects he's working on.

Some Basics
Tell me a bit about yourself.

How long have you been designing tabletop games?
Five to ten years.

Why did you start designing tabletop games?
It's an extension of my writing.

What game or games are you currently working on?
Death Derby expansion stuff (combat racing game), Post-apocalyptic Escapades (a 18+ RPG game), and Full Moon Tech (a capture type game in which rival biotech companies try to capture the most werewolf DNA before the government).

Have you designed any games that have been published?
Death Derby and The Disturbance Timeline RPG with its two modules.

What is your day job?
Was in call centers the last 5 years, but that's bad for my health and I'm in the process of switching things up.

Your Gaming Tastes
My readers would like to know more about you as a gamer.

Where do you prefer to play games?
Home.

Who do you normally game with?
Friends and family.

If you were to invite a few friends together for game night tonight, what games would you play?
It'd probably be up to them and it'd probably be Death Derby.

And what snacks would you eat?
Doritos.

Do you like to have music playing while you play games? If so, what kind?
Industrial Rock stuff (like Powerman 5k) and/or Industrial Techno (like Phosgore).

What's your favorite FLGS?
Don't have one.

What is your current favorite game? Least favorite that you still enjoy? Worst game you ever played?
My current favorite is my game Death Derby, there's not been repeat race in nearly 500 hours of playtime. Yahtzee. You Are the Maniac.

What is your favorite game mechanic? How about your least favorite?
No favorites, I just do what needs to be done to do what I want something to do and then to smooth it out.

What's your favorite game that you just can't ever seem to get to the table?
Any old Shadowrun tabletop game.

What styles of games do you play?
I like to play Board Games, Card Games, RPG Games, Video Games

Do you design different styles of games than what you play?
I like to design Card Games, RPG Games

OK, here's a pretty polarizing game. Do you like and play Cards Against Humanity?
No

You as a Designer
OK, now the bit that sets you apart from the typical gamer. Let's find out about you as a game designer.

When you design games, do you come up with a theme first and build the mechanics around that? Or do you come up with mechanics and then add a theme? Or something else?
I'm a writer, so the theme is always first. Furthermore, my main card games are an expansion of my RPG. Death Derby is the vehicle combat section pulled out and made into a game and Post-apocalyptic Escapades is a super stripped down version of the RPG itself.

Have you ever entered or won a game design competition?
No.

Do you have a current favorite game designer or idol?
Sid Meier

Where or when or how do you get your inspiration or come up with your best ideas?
Everywhere, but I also have a sandbox SF world that covers the next 2k years of human history that my SF and most the game stuff is set on.

How do you go about playtesting your games?
Extensively.

Do you like to work alone or as part of a team? Co-designers, artists, etc.?
Alone. Anything I need done is essentially contracted out as needed. Some playtesters also double as actors and cameramen, etc.

What do you feel is your biggest challenge as a game designer?
Marketing, but that's more on the publishing side.

If you could design a game within any IP, what would it be?
Arcanum: Of Steamworks and Magick Obscure

What do you wish someone had told you a long time ago about designing games?
Try it out sooner.

What advice would you like to share about designing games?
Playtest, playtest, and playtest. Then when you think you've playtested enough, playtest some more.

Would you like to tell my readers what games you're working on and how far along they are?
Published games, I have: Death Derby and The Disturbance Timeline RPG
Games that will soon be published are: Death Derby: Nature's Rage expansion
Games I feel are in the final development and tweaking stage are: Death Derby: High Octane
Games that I'm playtesting are: Post-apocalyptic Escapades
Games that are in the early stages of development and beta testing are: PA Escapades expansions: Mad Mansion and Escape from Xan
And games that are still in the very early idea phase are: Full Moon Tech, along with a few others: Scavenger Lords that stalled before Alpha, Post-apocalyptic Arena that failed initial playtests and was reworked into PA Escapades, and a serial killer capture game that was a collaboration which stalled a short ways into playtesting and inspired Full Moon Tech.

Are you a member of any Facebook or other design groups? (Game Maker's Lab, Card and Board Game Developers Guild, etc.)
The Game Crafter, the majority of FB groups are swamped with beginner questions and too noisy for real work.

And the oddly personal, but harmless stuff…
OK, enough of the game stuff, let's find out what really makes you tick! These are the questions that I'm sure are on everyone's minds!

Star Trek or Star Wars? Coke or Pepsi? VHS or Betamax?
Both. Pepsi. VHS.

What hobbies do you have besides tabletop games?
Writing, gardening, and taking care of my place.

What is something you learned in the last week?
That all the call centers in my town have bad air and I have to find another line of business to pay the bills.

Favorite type of music? Books? Movies?
Industrial. Non-fiction science and history. The ones not many others like like American History X and Fight Club.

What was the last book you read?
Several stories out of Stephen King's Everything's Eventual.

Do you play any musical instruments?
I wish.

Tell us something about yourself that you think might surprise people.
I'm going to try making my 1/2 acre of property self sufficient.

Tell us about something crazy that you once did.
I chased my married friend's husband out the door on break to apologize and risk a punch in the jaw to keep anyone involved from losing a job.

Biggest accident that turned out awesome?
I got a horrible infection in my left leg that cost me a job, but the job I went to is where I met a friend that helped me a great deal.

Who is your idol?
Neil Degrasse Tyson

What would you do if you had a time machine?
Probably run back and forth in time like I was on a road trip.

Are you an extrovert or introvert?
Introvert with short periods of extroversion.

If you could be any superhero, which one would you be?
Tony Stark

Have any pets?
Cats

When the next asteroid hits Earth, causing the Yellowstone caldera to explode, California to fall into the ocean, the sea levels to rise, and the next ice age to set in, what current games or other pastimes do you think (or hope) will survive into the next era of human civilization? What do you hope is underneath that asteroid to be wiped out of the human consciousness forever?
I think any game has a chance, which is why I want to make a couple stand alone card games, and the more those games teach as far as strategy goes, the more useful they'd be to anyone that finds them. Nothing would be wiped out though. Everything comes back around after enough time just like bell bottoms.

Just a Bit More
Thanks for answering all my crazy questions! Is there anything else you'd like to tell my readers?

I hope the interview thing doesn't bug out this far in. :)




Thank you for reading this People Behind the Meeples indie game designer interview! You can find all the interviews here: People Behind the Meeples and if you'd like to be featured yourself, you can fill out the questionnaire here: http://gjjgames.blogspot.com/p/game-designer-interview-questionnaire.html

Did you like this interview?  Please show your support: Support me on Patreon! Or click the heart at Board Game Links , like GJJ Games on Facebook , or follow on Twitter .  And be sure to check out my games on  Tabletop Generation.

Recycle Reuse

Seemed a shame to clear the table after just one game.



The original game was played with Don's 30mm Spencer Smith ACW figures but my first wargame book was his Battles With Model Soldiers and the figures were Airfix ACW so........


Hobby time has been curtailed this last week and casting & converting has taken precendence.

If all goes well I'll get to play on Wednesday.

Hybrid Heaven (N64)

Hybrid Heaven menu screen
Developer:Konami Osaka|Release Date:1999|Systems:Nintendo 64

Super Adventures is back again! It's only going to be around for eight weeks before going back into hibernation over the winter, but I'm going to be writing about so many games. Like, maybe even eight of them.

First I'm playing an N64 game called Hybrid Heaven. It's one of those games that I've been meaning to check out for years, but it's finally completed the arduous climb to the top of my 'to play' list. It made it just in time as well, as it's the game's 20th anniversary this year, though that's true of a lot of N64 titles. In fact my half-assed research on Wikipedia tells me that about a third of the system's games came out during 1999. Then after 2000 the console dropped like a rock for some reason (PlayStation 2).

Hybrid Heaven wasn't exactly the N64's biggest hit, but I don't feel like it can be that obscure, at least not to people who owned the system. I think it's probably one of those games that lots of people have heard of but not necessarily played themselves. It's one of the few carts my family had for the console back in the day and I even I haven't played it, though my brother did spoil the twist for me.

The game was nice enough to give me two title screens to pick from for my screenshot up there, but I decided to go with the one with menu options on it instead of the one with the Twin Towers filling the screen... because it gives me an excuse to talk about the resolution!

A few N64 games offer a 'high resolution' option if you've got the Expansion Pak installed, which doubles the resolution to 640x480. Or at least that's what you'd expect it to do, but it was apparently more like 480x360 for most games (or even less in widescreen). Hybrid Heaven seems to be one of the few N64 games that actually does something close to proper 640x480... but I've heard that the frame rate's terrible in that mode so I'm going to leave it on standard definition.

Read on »

2020. március 4., szerda

How A Private Club Affiliates To Mind Sports South Africa (MSSA).

Old Edwardian Mind Sports Club is the oldest club, with continuous membership, affiliated to MSSA.
Mind Sports South Africa (MSSA) is the national federation for Board games, Card games, Esports, and Wargames.

MSSA promotes all  the different disciplines equally, although each affiliated club may pick-and-choose which discipline it wishes to promote in its club. Some clubs will promote the whole gambit, while others will concentrate on only one discipline, and/or even just concentrate on one specific title.

The choice is ultimately up to the member club.

The various mind sports offer unique opportunities to many South Africans. Many Souuth Africans have been able to earn Regional, Provincial, and National Colours which have allowed them to earn bursaries and obtain first-class educations.

MSSA has sent teams with full Protea Colours to international events since 1991 for wargames, 1996 for Morabaraba, 1997 for Checkers, and 2005 for Esports. 


All selected have found being part of the national team to be an education in itself.. 

All clubs must be legal bodies, as well as being non-profit organizations. Thus each club needs to have a founding document. Associations may use the draft constitution provided below.

It is the club that is the member of MSSA, while the players are affiliated to the club.


Any applicant needs to be aware of the following:
  1. MSSA's Constitution
  2. MSSA's General Regulations
  3. Proforma Constitution - this is a draft constitution that is used by many clubs affiliated to MSSA, 
  4. An Application for Affiliation form,
  5. Registration Forms for all players – including the administrators and any/all coaches,
  6. The fee note form – please note that the fees for private clubs are R104.00 affiliation fee and R110.00 per player per annum, 
  7. The Letter of Undertaking, and
  8. A brochure about MSSA
In order to affiliate, the completed Application for affiliation Form must be submitted to the MSSA.

Once the Board has approved a club's affiliation, the club then needs to complete the Google Registration Page allocated to the club for the players and make payment.

All club members may participate in all events for which it qualifies. Such events include meetings, championships, courses, and so forth. 

Advantages of having a MSSA affiliated club: 

There are many advantages of having a MSSA affiliated club, such as:
  1. Being part of a community where your club has a real say in how things are done
  2. Being able to apply for National Lottery Funding – MSSA member clubs can apply for up to R800,000.00 in funding
  3. Being able to get assistance from your local government
  4. Experience increased media exposure of your events and your gamers
  5. Become part of the international community through the MSSA Registered players are able to become internationally recognised umpires, etc.
  6. Enable your gamers to take part in MSSA events, which may qualify them for Regional, Provincial, and National colours, overseas trips, and even sports bursaries at university.
MSSA's Constitution   

The Constitution forms the foundation of the MSSA. It guarantees members rights and governs the way that the MSSA operates. It can only be amended by a two-thirds majority at a Council Meeting. Please remember that Associations only have two (2) votes each, whereas member clubs have a representational vote, being: normal clubs: one vote per every five registered players, and school clubs: one vote per every ten registered players.

MSSA's General Regulations   


The General Regulations comprises of decisions made by both Council and Executive Committee Meetings. The General Regulations deals with how sub-committees operate as well as to how teams are selected and development funding is distributed.   Please refer to Schedule 10.12 in regard to the rights of clubs in hosting events.

MSSA's Discipline Specific Regulations   


The Discipline Specific Regulations deal with rules concerning the different disciplines. The Disciplines that the MSSA caters for are; Board Gaming, Card gaming, Esports, and Figure Gaming.


Application for Affiliation form   

When a club applies for membership, the applicant club must complete such form and return the same to the MSSA.

Fee note for 2020 

The fee note details the Affiliation Fees and Registration fees that are payable.

Player Registration Form   


The Player Registration Form needs to be completed by every player that is a member of a club and intends to participate in MSSA affairs.

MSSA's Letter of Undertaking   

The Letter of Undertaking is for all registered players who sit on any MSSA committee.

Social Media

The MSSA makes use of the following:
Should you have any queries whatsoever, please contact mindsportscorrespondence@gmail.com.

Tech Book Face Off: Getting Clojure Vs. Learn Functional Programming With Elixir

Ever since I read Seven Languages in Seven Weeks and Seven More Languages in Seven Weeks, I've been wanting to dig into some of the languages covered by those books a bit more, and so I've selected a couple of books on two interesting functional languages: Clojure and Elixir. For Clojure I narrowed the options down to Getting Clojure by Russ Olsen, and for Elixir I went with Learn Functional Programming with Elixir by Ulisses Almeida. You may notice that, like the Seven in Seven books, both of these books are from The Pragmatic Programmers. They seem to pretty consistently publish solid, engaging programming books, and I was hoping to have more good luck with these two books. We'll see how they turned out.

Getting Clojure front coverVS.Learn Functional Programming With Elixir front cover

Getting Clojure

I remember thoroughly enjoying Russ Olsen's Eloquent Ruby years ago, so my expectations were already set for this book. Olsen did not disappoint. While Getting Clojure is an introductory programming language book instead of a guide on the idioms and best practices of the language, like Eloquent Ruby was, he brings the same clear, concise writing, and nails the right balance between covering the minutia and sketching an overall picture of Clojure without boring the reader to tears.

Programming books that aim to teach a language from front to back can easily fall into the trap of spending too much time on all of the gory details about the language's arithmetic and logic systems or every possible control structure. Maybe it's because Clojure is a simple and straightforward language that doesn't have the complications that other languages have in these areas, but this book was a very easy read through these normally tedious parts. Olsen assumes the reader is already a programmer with a couple languages under their belt, so he lays out the mundane facts in a succinct, orderly manner and moves on to the more interesting bits.

Chapters are short and evenly spaced, each focusing on one small part of Clojure, starting off with the basics of arithmetic, variables, data types, logic, functions, and namespaces. Each chapter has sections at the end for discussing how to stay out of trouble when using those language features and what those features look like in actual Clojure programs. After the basics he covers the more intermediate topics of sequences, destructuring, records, tests, and specs before finishing things up with inter-operating with Java, working with threads, promises, futures, and state, and exploring the power of macros. It's a logical order that flows nicely, with later chapters building on earlier material through a gentle learning curve. I never felt stuck or frustrated, and I could read through a few chapters in a sitting at a rapid pace. That's testament to excellent technical writing skills that allow an experienced reader to go through the book at speed.

One fascinating thing about this book, and I imagine every Clojure book, is how little time is spent explaining syntax. Clojure is a Lisp-style language, so syntax is kept to a minimum. What do I mean by that? Well, the basic syntax of Clojure is a function call, followed by its arguments, both wrapped in parentheses like so:

(println "Hello, World!")

Vectors are denoted with [] and maps follow the form of {:key1 value1 :key2 value2}. Nearly all of the code looks like this, just with more complicated nesting of functions. After learning the standard library functions, you know and understand about 90% of the language! The more advanced language features like promises and macros add some more syntactical sugar, but really, compared to C-style languages, Clojure's syntax is incredibly lightweight. Some programmers may hate all of the parentheses, and the prefix arithmetic notation takes some getting used to, but learning a language that's so consistent in its structure is enlightening.

Not only does Clojure have the elegance of a Lisp, but it also runs on the JVM so we have access to all of the Java libraries that have been built up over the last few decades. That may not always seem like a benefit, considering how convoluted some Java libraries are, but Clojure has its own great features that should take precedence over the uglier parts of Java while still being able to leverage all of the time-saving work that's been done already.

Plus, Clojure has made significant advances in modern concurrent programming, both through its inherent nature as a functional language with immutable data structures, and because of safe concurrent programming structures like promises and futures. As Olsen says about threads, "One of the things that makes programming such a challenge is that many of our sharpest tools are also our most dangerous weapons." If concurrency is anything, it's hard, but Clojure makes this increasingly important programming paradigm easier and safer, as long as you know how to use those sharp tools.

Olsen has done a great job of teaching the set of tools available in Clojure with this book, and beyond it being clear and well written, it was a fun read all the way through. I love learning new languages and the new programming tools that they reveal, especially when I can find a great field guide like this one to help me along the way. If you don't know Clojure and would like to learn, Getting Clojure is a highly recommended read.

Learn Functional Programming with Elixir

Like Clojure, I wanted to dig more deeply into Elixir after reading about it in Seven More Languages in Seven Weeks. This book showed some promise as a quick introduction to the language that would focus on the functional programming paradigm. I think the title is a bit of a misnomer, though, because it was more on the side of a quick introduction to Elixir, which just happens to be a functional language. Almeida did not go into too much detail about how to use the functional paradigm to greatest advantage, and instead stuck to the basics.

Spending time on the basics is fine, of course. It just wasn't what I was expecting. The book is split into seven chapters that cover a quick introduction of what Elixir looks like, variables and functions, pattern matching and control flow, recursion, higher-order functions (like each, map, and filter), an extended example text game, and impure functions. Notably missing from this list is anything having to do with concurrency and parallelism—Elixir's primary claim to fame, being that it runs on the Erlang VM. But this is a beginner's book, after all, and it keeps things pretty simple, although the pace is probably too fast and the explanations too short for someone who has never programmed before. This book is definitely meant for experienced programmers looking to get started with Elixir quickly.

In that respect, the book accomplishes its goal quite well. It presents all of the basic features of Elixir in a logical and succinct manner, covering all of the different syntax elements of the language without much ceremony. Elixir has its fair share of syntax, too, much more so than Clojure does. Whereas Clojure consists entirely of function calls, Elixir syntax is much more exotic:

max = fn
x1, x2 when x1 >= x2 -> x1
_, x2 -> x2
end
This is a simple function that returns the maximum of two numbers, but it shows some of the more extensive syntax of Elixir with pattern matching on the second and third lines, the when guard clause, the underscore used as a wildcard matcher, and the anonymous function declaration. When this function is called, if line 2 matches, including the guard clause such that x1 >= x2, then x1 is returned. Otherwise, line 3 will match automatically and x2 is returned. This is just a sampling of syntax, too. Things get even more involved with lists and maps and function arguments, all mixed in with pattern matching and pipes. This is a rich language, indeed.

The brief explanations of all of these language features tended to be a bit wanting. They were so clipped and simple that I was often left wondering if there wasn't much more to some of the features that I was missing. The writing style was abrupt and disjointed to the point of being robotic. Here is one example when discussing recursion:
Code must be expressive to be easier to maintain. Recursion with anonymous functions isn't straightforward, but it is possible. In Elixir, we can use the capturing feature to use named function references like anonymous functions:
Here's another example when describing the Enum module:
The Enum functions work like our homemade functions. The Enum module has many useful functions; it's easy to guess what they do from their names. Let's take a quick look:
This kind of writing just starts to grate on me because it has no natural flow to it. I would end up skimming over much of the explanations to try to pick out the relevant bits without feeling like I might be assimilated by the Borg.

Most of the code examples were forgettable as well. They did an adequate job of showing off the language features that they were meant to showcase, but they certainly didn't serve to inspire in any way. On the other hand, chapter 6 on the extended example of a text game was quite delightful. This chapter made up for most of those other faults, and made the book almost worthwhile.

In the example game, you code up a simple text-based dungeon crawler where you can pick a hero and move through a dungeon fighting monsters. It's an incredibly stripped down game, since it's developed in only about 35 pages, but it shows Elixir in a real application setting, using all of the language features that were introduced in the rest of the book. It was fun and illuminating, and I wish the rest of the book could have been done in the same way, explaining all of the Elixir syntax through one long code example.

Alas, it was not done that way, but even though the rest of the book was terse and didn't cover some of Elixir's more advanced features, it was still a decent read. It was short and to the point, making it useful for a programmer new to Elixir that needs to get going with the language right now. For anyone looking to learn Elixir more thoroughly, and maybe more enjoyably, you'll want to look somewhere else.


Of the two books, clearly Getting Clojure wins out over Learn Functional Programming With Elixir. Olsen showed once again how to write a programming book well, while the Elixir book was mechanical and insufficient. That's great if you're in the mood to learn Clojure, but what about Elixir? It's a fascinating language, but I'll have to look further to find a good book for learning the details.

2020. február 24., hétfő

Download IGI 2 Covert Strike Highly Compressed For Pc

Download IGI 2 Covert Strike Highly Compressed For Pc

IGI 2 Covert Strike Full Review

Welcome to IGI 2 Covert Strike is one of the best Shooting game especially for shooting lovers that has been developed by Innerloop published by Codemasters.This game was released on March 3,2003.


Screenshot



IGI 2 Covert Strike System Requirements

Following are the minimum system requirements of IGI 2.
  • Operating System: Windows XP/ Windows Vista/ Windows 7/ Windows 8 and 8.1
  • CPU: Pentium 4 1.4GHz
  • RAM: 512 MB
  • Hard Disk Space: 2 GB




2020. február 20., csütörtök

fw: help me remove bad articles from google

Remove those annoying ripoff reports or even trustpilot reviews, scam
advisor reviews
clean up your reputation
http://monkeydigital.tk/product/reputation-management/

regards
Nereida Duncan










http://monkeydigital.tk/unsubscribe/

PUBG Mobile Erangel Map Is Getting A Redesign

About Erangel map:


Erangel map is one of the four playable maps in PUBG. According to a research, more than 80% of PUBG players love Erangel map. This may be due to the existence of high loot, good weapons, tall grass, good hiding locations etc. Erangel map has also a sad untold story.

Reasons behind the update:



Recently, PUBG Corp announced an update regarding Erangel map. This is because many PUBG mobile players have complained to the official PUBG support regarding Erangel map. According to them, they have experienced the following problems:

1.
 The increase of bugs and glitches in Erangel map.

2. The increase of lag while playing PUBG.


3
. The sudden crashing of the game while playing in Erangel map.

4.
 Famous loot locations like Georgopol, Sosnovka military base etc. have very few loots now. 

Understanding the problems of PUBG players, PUBG developers have taken a big decision. They decided that Erangel map will be redesigned to improve such errors. They are working on the development of Erangel map. They added that this could take a few months time to finish. 

Since loot locations are lacking loot so they assured that the new updated Erangel map will have proper loot locations. They mentioned that some parts of the Erangel map may be changed to make it more interesting for players. 

The PUBG team have also decided to work on bugs and glitches and lagging of servers and to improve gameplay.

Which parts will be updated?


An image went viral through a Reddit post when a user posted it claiming that the red dots in the image will be updated in Erangel map. The image is given below:

PUBG mobile erangel map update
Source: Imgur                       Erangel map update locations


The PUBG team responded to the image saying" As some of you inferred from recent leaks of a map image, we are working on new ways to balance loot and otherwise improve our maps, Erangel being the first. The addition of compounds is just one way we're testing internally, but is certainly not the ONLY way."

They later added that" Keep in mind that leaked images are usually just a snapshot in time and rarely represent the entire plane or scope of what's being worked on."

The above words said by PUBG Corp. may suggest that after the Erangel map update, the other maps may be redesigned too.

Release date:


As mentioned above, this update of Erangel map will take a few months time for PUBG developers to finish. The PUBG team has not officially announced any date.

But we expect to get this update after 0.11.5 update i.e  0.12.0 or  0.12.5  update version.

Are you excited about this Erangel map update? What are your thoughts about this update and what update you want? We are curious to know in the comments section below!