Friday, March 29, 2019

The Ultimate List of The 17 Best URL Shortener Services 2019

  1. Fas.li: Although Fas.li is relatively new URL Shortener Service, it has made its name and is regarded as one of the most trusted URL Shortener Company. It provides a wonderful opportunity for earning money online without spending even a single $. You can expect to earn up to $15 per 1000 views through Fas.li.
    You can start by registering a free account on Fas.li, shrink your important URLs, and share it with your fans and friends in blogs, forums, social media, etc. The minimum payout is $5, and the payment is made through PayPal or Payza on 1st or 15th of each month.
    Fas.li also run a referral program wherein you can earn a flat commission of 20% by referring for a lifetime. Moreover, Fas.li is not banned in anywhere so you can earn from those places where other URL Shortening Services are banned.
  2. Al.ly: Al.ly is another very popular URL Shortening Service for earning money on short links without investing any single $. Al.ly will pay from $1 to $10 per 1000 views depending upon the different regions. Minimum withdrawal is only $1, and it pays through PayPal, Payoneer, or Payza. So, you have to earn only $1.00 to become eligible to get paid using Al.ly URL Shortening Service.
    Besides the short links, Al.ly also runs a referral program wherein you can earn 20% commission on referrals for a lifetime. The referral program is one of the best ways to earn even more money with your short links. Al.ly offers three different account subscriptions, including free option as well as premium options with advanced features.
  3. Ouo.io: Ouo.io is one of the fastest growing URL Shortener Service. Its pretty domain name is helpful in generating more clicks than other URL Shortener Services, and so you get a good opportunity for earning more money out of your shortened link. Ouo.io comes with several advanced features as well as customization options.
    With Ouo.io you can earn up to $8 per 1000 views. It also counts multiple views from same IP or person. With Ouo.io is becomes easy to earn money using its URL Shortener Service. The minimum payout is $5. Your earnings are automatically credited to your PayPal or Payoneer account on 1st or 15th of the month.
    • Payout for every 1000 views-$5
    • Minimum payout-$5
    • Referral commission-20%
    • Payout time-1st and 15th date of the month
    • Payout options-PayPal and Payza

  4. Short.pe: Short.pe is one of the most trusted sites from our top 30 highest paying URL shorteners.It pays on time.intrusting thing is that same visitor can click on your shorten link multiple times.You can earn by sign up and shorten your long URL.You just have to paste that URL to somewhere.
    You can paste it into your website, blog, or social media networking sites.They offer $5 for every 1000 views.You can also earn 20% referral commission from this site.Their minimum payout amount is only $1.You can withdraw from Paypal, Payza, and Payoneer.
    • The payout for 1000 views-$5
    • Minimum payout-$1
    • Referral commission-20% for lifetime
    • Payment methods-Paypal, Payza, and Payoneer
    • Payment time-on daily basis

  5. Shrinkearn.com: Shrinkearn.com is one of the best and most trusted sites from our 30 highest paying URL shortener list.It is also one of the old URL shortener sites.You just have to sign up in the shrinkearn.com website. Then you can shorten your URL and can put that URL to your website, blog or any other social networking sites.
    Whenever any visitor will click your shortener URL link you will get some amount for that click.The payout rates from Shrinkearn.com is very high.You can earn $20 for 1000 views.Visitor has to stay only for 5 seconds on the publisher site and then can click on skip button to go to the requesting site.
    • The payout for 1000 views- up to $20
    • Minimum payout-$1
    • Referral commission-25%
    • Payment methods-PayPal
    • Payment date-10th day of every month

  6. Cut-win: Cut-win is a new URL shortener website.It is paying at the time and you can trust it.You just have to sign up for an account and then you can shorten your URL and put that URL anywhere.You can paste it into your site, blog or even social media networking sites.It pays high CPM rate.
    You can earn $10 for 1000 views.You can earn 22% commission through the referral system.The most important thing is that you can withdraw your amount when it reaches $1.
    • The payout for 1000 views-$10
    • Minimum payout-$1
    • Referral commission-22%
    • Payment methods-PayPal, Payza, Bitcoin, Skrill, Western Union and Moneygram etc.
    • Payment time-daily

  7. Wi.cr: Wi.cr is also one of the 30 highest paying URL sites.You can earn through shortening links.When someone will click on your link.You will be paid.They offer $7 for 1000 views.Minimum payout is $5.
    You can earn through its referral program.When someone will open the account through your link you will get 10% commission.Payment option is PayPal.
    • Payout for 1000 views-$7
    • Minimum payout-$5
    • Referral commission-10%
    • Payout method-Paypal
    • Payout time-daily

  8. Bc.vc: Bc.vc is another great URL Shortener Site. It provides you an opportunity to earn $4 to $10 per 1000 visits on your Shortened URL. The minimum withdrawal is $10, and the payment method used PayPal or Payoneer.
    Payments are made automatically on every seven days for earnings higher than $10.00. It also runs a referral system wherein the rate of referral earning is 10%.
    • The payout for 1000 views-$10
    • Minimum payout -$10
    • Referral commission-10%
    • Payment method -Paypal
    • Payment time-daily

  9. LINK.TL: LINK.TL is one of the best and highest URL shortener website.It pays up to $16 for every 1000 views.You just have to sign up for free.You can earn by shortening your long URL into short and you can paste that URL into your website, blogs or social media networking sites, like facebook, twitter, and google plus etc.
    One of the best thing about this site is its referral system.They offer 10% referral commission.You can withdraw your amount when it reaches $5.
    • Payout for 1000 views-$16
    • Minimum payout-$5
    • Referral commission-10%
    • Payout methods-Paypal, Payza, and Skrill
    • Payment time-daily basis

  10. Linkrex.net: Linkrex.net is one of the new URL shortener sites.You can trust it.It is paying and is a legit site.It offers high CPM rate.You can earn money by sing up to linkrex and shorten your URL link and paste it anywhere.You can paste it in your website or blog.You can paste it into social media networking sites like facebook, twitter or google plus etc.
    You will be paid whenever anyone will click on that shorten a link.You can earn more than $15 for 1000 views.You can withdraw your amount when it reaches $5.Another way of earning from this site is to refer other people.You can earn 25% as a referral commission.
    • The payout for 1000 views-$14
    • Minimum payout-$5
    • Referral commission-25%
    • Payment Options-Paypal,Bitcoin,Skrill and Paytm,etc
    • Payment time-daily

  11. Short.am: Short.am provides a big opportunity for earning money by shortening links. It is a rapidly growing URL Shortening Service. You simply need to sign up and start shrinking links. You can share the shortened links across the web, on your webpage, Twitter, Facebook, and more. Short.am provides detailed statistics and easy-to-use API.
    It even provides add-ons and plugins so that you can monetize your WordPress site. The minimum payout is $5 before you will be paid. It pays users via PayPal or Payoneer. It has the best market payout rates, offering unparalleled revenue. Short.am also run a referral program wherein you can earn 20% extra commission for life.
  12. BIT-URL: It is a new URL shortener website.Its CPM rate is good.You can sign up for free and shorten your URL and that shortener URL can be paste on your websites, blogs or social media networking sites.bit-url.com pays $8.10 for 1000 views.
    You can withdraw your amount when it reaches $3.bit-url.com offers 20% commission for your referral link.Payment methods are PayPal, Payza, Payeer, and Flexy etc.
    • The payout for 1000 views-$8.10
    • Minimum payout-$3
    • Referral commission-20%
    • Payment methods- Paypal, Payza, and Payeer
    • Payment time-daily

  13. Linkbucks: Linkbucks is another best and one of the most popular sites for shortening URLs and earning money. It boasts of high Google Page Rank as well as very high Alexa rankings. Linkbucks is paying $0.5 to $7 per 1000 views, and it depends on country to country.
    The minimum payout is $10, and payment method is PayPal. It also provides the opportunity of referral earnings wherein you can earn 20% commission for a lifetime. Linkbucks runs advertising programs as well.
    • The payout for 1000 views-$3-9
    • Minimum payout-$10
    • Referral commission-20%
    • Payment options-PayPal,Payza,and Payoneer
    • Payment-on the daily basis

  14. Clk.sh: Clk.sh is a newly launched trusted link shortener network, it is a sister site of shrinkearn.com. I like ClkSh because it accepts multiple views from same visitors. If any one searching for Top and best url shortener service then i recommend this url shortener to our users. Clk.sh accepts advertisers and publishers from all over the world. It offers an opportunity to all its publishers to earn money and advertisers will get their targeted audience for cheapest rate. While writing ClkSh was offering up to $8 per 1000 visits and its minimum cpm rate is $1.4. Like Shrinkearn, Shorte.st url shorteners Clk.sh also offers some best features to all its users, including Good customer support, multiple views counting, decent cpm rates, good referral rate, multiple tools, quick payments etc. ClkSh offers 30% referral commission to its publishers. It uses 6 payment methods to all its users.
    • Payout for 1000 Views: Upto $8
    • Minimum Withdrawal: $5
    • Referral Commission: 30%
    • Payment Methods: PayPal, Payza, Skrill etc.
    • Payment Time: Daily

  15. CPMlink: CPMlink is one of the most legit URL shortener sites.You can sign up for free.It works like other shortener sites.You just have to shorten your link and paste that link into the internet.When someone will click on your link.
    You will get some amount of that click.It pays around $5 for every 1000 views.They offer 10% commission as the referral program.You can withdraw your amount when it reaches $5.The payment is then sent to your PayPal, Payza or Skrill account daily after requesting it.
    • The payout for 1000 views-$5
    • Minimum payout-$5
    • Referral commission-10%
    • Payment methods-Paypal, Payza, and Skrill
    • Payment time-daily

  16. Oke.io: Oke.io provides you an opportunity to earn money online by shortening URLs. Oke.io is a very friendly URL Shortener Service as it enables you to earn money by shortening and sharing URLs easily.
    Oke.io can pay you anywhere from $5 to $10 for your US, UK, and Canada visitors, whereas for the rest of the world the CPM will not be less than $2. You can sign up by using your email. The minimum payout is $5, and the payment is made via PayPal.
    • The payout for 1000 views-$7
    • Minimum payout-$5
    • Referral commission-20%
    • Payout options-PayPal, Payza, Bitcoin and Skrill
    • Payment time-daily

  17. Adf.ly: Adf.ly is the oldest and one of the most trusted URL Shortener Service for making money by shrinking your links. Adf.ly provides you an opportunity to earn up to $5 per 1000 views. However, the earnings depend upon the demographics of users who go on to click the shortened link by Adf.ly.
    It offers a very comprehensive reporting system for tracking the performance of your each shortened URL. The minimum payout is kept low, and it is $5. It pays on 10th of every month. You can receive your earnings via PayPal, Payza, or AlertPay. Adf.ly also runs a referral program wherein you can earn a flat 20% commission for each referral for a lifetime.

The Art Of Video Games: Doki Doki Literature Club


SPOILER ALERT: Plot details follow for Doki Doki Literature Club and School Days






By now, most everyone knows that Doki Doki Literature Club is subversive in some way, but I imagine that those first few who downloaded the game suspected nothing of the sort. On the surface, it looks like a regular dating visual novel, with four different anime archetypes ready to fall for you. The game can be played for free, is fairly short, and has little to with literature, so it would otherwise be forgettable, and yet...

Despite not being from Japan, Doki Doki perfectly mimics the standard visual novel formula. You are pushed by Sayori, the ditzy best friend who probably has a crush on you, to join the high school's literature club. The club's members include Yuri, the quiet, but well-endowed kuudere who enjoys horror, Natsuki, the abrasive tsundere who has taste for cute things like baking and manga, and finally the leader, Monika, the well-rounded leader of the club who weirdly resembles Sailor Jupiter.  You are assigned to write poems for the club each night, picking out words associated to the interests of whomever you want to get closer with. These choices get you into some genuine romantic moments, from popping chocolate into Yuri's lips or tasting the cream off of Natsuki's finger. You can get so wrapped up in the heat of the moment, that you forget about the other shoe that's due to drop, and drop it does.

Sayori, it turns out, is depressed. She's only cheerful when you're around, a delightful distraction from her deteriorating state. We get a hint of this from her last poem, When she confesses her love for you, you can either accept her as lover or friend. It doesn't matter, because the end result is the same. The next morning, you enter her home and find her hanging by a rope. This is by far the scariest and most unsettling part of the game. The lack of blood and creepy music certainly help in that measure. It's fitting that Sayori's suicidal depression isn't cured by a confession of love, as that is hardly ever the case in real life. Some things are out of our control.

From here on out, the game devolves into psychological horror. You are encouraged to start a new game, with Sayori's face blurred on the menu screen. You join the club afresh, but Sayori has been erased from existence. Occasionally the game glitches, with unreadable text and distorted faces. Like the music genres of vaporwave and future funk, Doki Doki reuses the generic computer effects we're all familiar with for aesthetic effect. Further, we see that Yuri and Natsuki are far more distressed than they entail. Their poetry starts to reflect this. It's implied that Natsuki is neglected or abused at home, and that her short stature is due to malnutrition. Yuri jokes about her scrounging for coins under the vending machine, while Monika tosses her a candy bar and she gobbles it up like a dog. Her love for manga is an escape. If you neglect Natsuki, there's a jump scare where her neck snaps at a right angle, and she rushes toward you. Yuri's shyness hides her extreme possessiveness of you. She is also masochistic, taking breaks at the drinking fountain to cut herself. Yuri isn't a yandere who would harm others for your love. She would only harm herself. So when she confesses her love, the ecstasy of emotion is so great that she stabs herself to death. You are left with her corpse for the weekend while unnerving music drones on. This is where making multiple saves is useful. Go to an earlier save, and you'll be made to spend the weekend with "Only Monika." Even the movement of the mouse is restricted to force your hand.

Here we see the game's mastermind, Monika. You sit in an empty classroom with her, while space drifts in the windows. In a fourth wall break worthy of Metal Gear Solid, Monika reveals that she knows her reality is a video game. So whenever you quit the game, she feels the pain of death. What Monika wants more than anything is to be "best girl" and loved by the protagonist, but she's never picked. Monika is most well-rounded of the four, and so, the least "dere". She isn't an kawaiified exaggeration of certain traits into a character. Monika even makes note that few would be attracted to actual personalities like Yuri or Natsuki in real life. All that makes them human is stripped away, while only the cutest parts are retained. Monika, however, is the yandere of this story, deleting the character files of the other girls from the game to eliminate the competition. Now she has you trapped to stare at forever. Try and quit the game, and she'll be right waiting for you when you restart. The only way to defeat her is to delete her character file from the game. A rather clever option. You start the game over again, with Monika gone from the club, and Sayori now realizing that she can be in control of the game. To keep things from repeating themselves, Monika decides to destroy the game in its entirety. The tragedy of Monika is that all she wanted to do was be loved, but was trapped within a system where that was impossible. By the end of the game, her only true act of love is to let you go.

The visual novel, School Days, could be considered the spiritual progenitor to Doki Doki Literature Club. The anime adaptation, which follows the game fairly well as a harem anime, takes on one of the "bad endings" as its finale. Makoto, the protagonist, had treated the girls around him like meat, sleeping with them and throwing them out. So one of the girls he's cheated on, Sekai, stabs him to death out of jealousy. Makoto's other girlfriend, Kotonoha, returns the favor by, not only killing Sekai, but opening her womb to ensure she wasn't carrying Makoto's child. Kotonoha then takes her dead boyfriend's head with her on a "nice boat." An ending as ridiculous as it was shocking. Some argue that School Days is a subversion or deconstruction of harem anime and visual novels, since it features the consequences of cheating on all these girls. This interpretation gives the story far too much credit. In order to deconstruct something, you must first construct it. The School Days anime has a superficial understanding of what draws people to the girls in visual novels. The anime assumes that we'd just all want to sleep with them like Makoto. If people only wanted to have sex with visual novel characters, they'd be watching hentai. People play visual novels because they also want an emotional connection with the personalities, but there is no intimacy in School Days. We don't care about any of these characters. We pity them, yes, but we don't care for them. Doki Doki strings you along long enough to make you care for Natsuki, Yuri, and Sayori. That is what makes their dark turns all the more horrifying to watch.

Doki Doki also fits well within recent trends in anime that meditate on the nature of fantasy and escapism. Porter Robinson and Madeon's Shelter music video features a survivor of the apocalypse who lives in a simulated reality to forget her loss. Gainax also did two anime music videos of this nature during their Anime Expo. The first, ME!ME!ME!, by Daoko and Teddyloid, was about an otaku forced to confront the virtual girls he become attached to. The second, Girl, also by Daoko, portrayed a lonesome girl lost in her own sexual imagination. The isekai ("parallel world") anime, Re:Zero, stars a protagonist is transported to a fantasy world, and thinks that, knowing all the tropes, he'll waltz right into the elf-girl's lap. Yet his ego and arrogance, which often succeed in shonen genres, lead him into disastrous choices. The game could've suffered to make better use of literary reference, being that this was supposed to be a "literature club." The best we get is a name-drop of Shel Silverstein. A shame that the game didn't mention Stephen King's Misery, Murakami Ryu's Audition, or Gilligan Flynn's Gone Girl. Maybe I ask for too much, but the dearth of literature in the "literature club" is sheer wasted potential.

Regardless, Doki Doki Literature Club is a video game that plays with the idea of video games, particularly visual novels, and what we want when we play them. For a visual novel, it's nowhere near as involving as, say, Danganronpa, but it plays with your assumptions in how to go about playing one. It makes you stop and think.



The Art Of Video Games


"The Art Of Video Games: Tetris."
http://sansuthecat.blogspot.com/2014/11/the-art-of-video-games-tetris-at-30.html

"The Art Of Video Games: Pac-Man."
http://sansuthecat.blogspot.com/2015/05/the-art-of-video-games-pac-man-at-35.html

"The Art Of Video Games: Super Mario Bros."
http://sansuthecat.blogspot.com/2015/06/the-art-of-video-games-super-mario-bros.html

"The Art Of Video Games: Super Smash Bros."
http://sansuthecat.blogspot.com/2015/06/the-art-of-video-games-super-smash-bros.html

"The Art Of Video Games: Final Fantasy VI."
http://sansuthecat.blogspot.com/2016/01/the-art-of-video-games-final-fantasy-vi.html

"The Art Of Video Games: Pokemon."
http://sansuthecat.blogspot.com/2016/05/the-art-of-video-games-pokemon.html

"The Art Of Video Games: The Legend Of Zelda."
http://sansuthecat.blogspot.com/2016/05/the-art-of-video-games-legend-of-zelda.html

"The Art Of Video Games: Final Fantasy IV."
http://sansuthecat.blogspot.com/2016/06/the-art-of-video-games-final-fantasy-iv.html

"The Art Of Video Games: Kingdom Hearts."
http://sansuthecat.blogspot.com/2016/06/the-art-of-video-games-kingdom-hearts.html

"The Art Of Video Games: Kingdom Hearts II."
http://sansuthecat.blogspot.com/2016/12/the-art-of-video-games-kingdom-hearts-ii.html

"The Art Of Video Games: The Last Of Us."
https://sansuthecat.blogspot.com/2017/06/the-art-of-video-games-last-of-us.html

"The Art Of Video Games: Persona 4."
https://sansuthecat.blogspot.com/2017/07/the-art-of-video-games-persona-4.html

"The Art Of Video Games: Danganronpa."
https://sansuthecat.blogspot.com/2017/07/the-art-of-video-games-danganronpa.html

"The Art Of Video Games: Final Fantasy VII."
https://sansuthecat.blogspot.com/2017/07/the-art-of-video-games-final-fantasy-vii.html

"The Art Of Video Games: Persona 3."
https://sansuthecat.blogspot.com/2017/08/the-art-of-video-games-persona-3.html


"The Art Of Video Games: Persona 5."
https://sansuthecat.blogspot.com/2017/12/the-art-of-video-games-persona-5.html





Ep 38: A Tankful Of Lard Is Live!

Ep 38: A Tankful of Lard is live!
https://soundcloud.com/user-989538417/episode-38-a-tankful-of-lard

Join the conversation at https://theveteranwargamer.blogspot.com, email theveteranwargamer@gmail.com, Twitter @veteranwargamer

What a Tanker!
https://toofatlardies.co.uk/product-category/what-a-tanker/

Veteran Wargamer What a Tanker play through
https://www.youtube.com/watch?v=ym5Fw996JbE&lc=

Too Fat Lardies What a Tanker - an introduction
https://www.youtube.com/watch?v=DWE_ShqU5L8

What a Tanker Twitter thread
https://twitter.com/VeteranWargamer/status/985596472128401408

What a Tanker FB Group
https://www.facebook.com/groups/934280466751499/

Music courtesy bensound.com. Recorded with zencastr.com. Edited with Audacity. Make your town beautiful; get a haircut.

Movie Reviews: Ready Player One, Game Night, Three Billboards Outside Ebbing Missouri, The Phantom Thread, Loving Vincent

See all of my movie reviews.

Sorry guys; five disappointing movies ...

Ready Player One: From Steven Spielberg, this is a shallow, uninteresting movie is about a guy who plays in a virtual world looking for three Easter eggs, or "keys", so that he can gain ownership of the company that owns the virtual world. While he is at it, others are also looking for the keys, one of whom is a woman who joins him as love interest (along with some other guild members), as well as certain high-financed players backed by people who are willing to kill you in the real world if they discover who you are and that you are a competitor.

Within five minutes of the start of the movie I found myself not caring about the boy or anyone else, since there is zero character development. Astonishingly, the amount I cared continued to drop as the movie went along. I didn't think that was possible, since I already didn't care at all, but I managed to continue to care less and less. I eventually figured out that this was because the score was very good. It cued me into thinking, every once in a while, that something that I might care about was about to occur. Each time, however, this never happened.

The amusement of the movie is supposed to come from a) watching other people play video games, which is a colossal bore (unless the player knows how to fill the time with snarky commentary, as people often do on YouTube), and b) seeing hundreds of throwbacks to 1980s video games and fiction. Unlike recent media in which this worked, such as Stranger Things and even Super 8 to an extent, it did not work here. I didn't get 90% of the references, and, anyway, simply seeing references on screen is not what made those other media good; the other media had good stories. And, I guess, we are supposed to be amused by c) the suspense as to whether the main character will solve the rather obvious and uninteresting puzzles and ultimately find the keys and triumph. Duh.

There is not a scrap of emotion in the entire movie. Someone gets killed at one point, but it's someone who we were barely introduced to and who is not shown as having any emotional connection to the main character. I am really in shock at this. This is the emotionally manipulative director who brought us Jaws? E.T.? Shindler's List? Bridge of Spies?

Whatever. I guess, while it is a useless and dull movie, it is not particularly offensive, at least. Oh wait, it is: at the end of the movie the narrator tells us that we shouldn't be spending all of our time playing video games / in virtual reality, but should instead interact with each other more in the real world. Thanks for that very important message; never would have known that.

One more thing that irritated me: T.J. Miller played the exact same character in this movie that he played in Silicon Valley. I liked it in Silicon Valley, but it was pretty out of place here.

Game Night: This is ninety minutes of one joke, the kind of joke that is funny only if it comes once, unexpectedly, in the middle of an otherwise serious situation, but is not funny when it comes repeatedly for ninety minutes. This is a farcical remake of The Game (1997, Michael Douglas). Instead of a strange combination of gaslighting, pursuit, and trying to figure out what is going on as the terror mounts, in this movie the terror happens, but everyone keeps making stupid jokes. It's supposed to be funny, because they keep making light of things while bad things happen; that's the one and only joke, really. The acting, directing, and cinematography were fine. Jason Bateman and Rachel McAdams are always cute.

The movie that did this well is The Man Who knew Too Little (1997, Bill Murray), which was a cute and silly movie. I was appalled enough at this movie to happily walk outside the movie theater twice to answer phone calls (I had it on vibrate, guys). If my friends hadn't been with me in the theater, I would have gone home and not gone back in to the theater to finish the movie. In the movie's defense, my friends liked it. They said that they like to see a mindless, silly movie once in a while (I think that's a slight directed at me and my movie choices).

Three Billboards Outside Ebbing Missouri: This is a well-acted, grim piece of midwest Americana. Mildred's (Fances McDermott) daughter was raped and murdered several months ago, but she hasn't heard anything from the police who are busy (according to her) chasing and shooting blacks who aren't really doing anything. So she puts up some billboards that pointedly call out the chief of police (Woody Harrelson) in a low-trafficked area. What makes it interesting is that a) she is actually friends with the chief of police, b) the chief is dying of cancer and should really not be at work, and c) the rest of the police dept doesn't take kindly to this, especially one lunatic racist violent hotheaded police creep. Things come to a boil, especially after the police chief shoots himself.

This movie is relentlessly depressing, representing a lot of the worst aspects of American prejudice, violence, despair, and hatred. Just about nobody supports Midred, not even her son. Interestingly, the lunatic police guy actually makes a kind of (unbelievable) change around two thirds into the movie. This should have given us a bit of hope. However, the movie ends just as bleakly and miserably as it started.

Other than being relentlessly depressing, what actually ruins the movie for me are the multiple acts of outrageous criminal behavior performed by multiple people on multiple occasions, some of it incredibly brutal and most of it performed in sight of multiple witnesses. These acts are done and never have repercussions. And I'm not saying that the bad guys weasel their way out of repercussions, I'm saying that the movie doesn't seem to believe that any reactions by the witnesses or police is expected. What the hell? Is this a video game? While I expect to sometimes find injustice in the system, the system still exists; treating violence like it's just a video game broke the reality of the movie for me.

The movie has compelling performances and some good ideas, but it's ultimately not realistic enough to recommend.

The Phantom Thread: Daniel Day Lewis gives another astounding performance as Reynolds, a dressmaker / bachelor / bully and all around a**hole in 1950s London. He is joined by other great performances by Vicky Krieps, Lesley Manville, and everyone else in this beautifully shot and artfully scripted period piece about a dressmaker who obsessively creates beautiful dresses, but only if his cadre of assistants take care of his other needs and none of them interrupts his "solitary genius" thinking. This genius is, apparently, sufficient excuse for everyone to give him his way, and for him to throw toxic vitriol at anyone who expresses any kind of opinion, presence, or personality. Like a spoiled baby, as one of the other main characters eventually says.

Krieps plays a waitress, Anna, who is drawn to this bully and who follows him to London to be a dress model and eventually a lover. She falls deeply in love with him - because he is such a genius - and even goes and does some of his bullying for him, both - because he is such a genius - and because she hopes he will one day fall in love with her and allow her to butter her toast in his presence without cursing her out. Even taking into account that this is the 1950s, she is really pathetic; in the first two thirds of the movie, not a moment is shown where she has a relationship with anyone else but him. No family? No friends or neighbors at all?

SPOILERS follow, because really you shouldn't watch this movie, and if you do you should be prepared for what happens.

Anna has a little strength in her, just enough to keep wanting him to love her. And so, one day after she suffers great abuse from him, she poisons him, and he falls sick and can't work for the next few days he is too sick to abuse her, so she is happy. And then, he comes back from his illness and proposes to her.

Okay ... but maybe he doesn't know that she poisoned him?

After the marriage, things go back to as they were, obviously, and he begins to heap abuse at her again until one day she overhears him complaining about how he doesn't want her around as she is disrupting his work. So she poisons him again, and this time he knows it and goes along with it. And he loves her.

And that's the movie. Okay...

So this is a sick, toxic (literally) relationship that works for both of them. She is only happy when he is poisoned and helpless, and he, despite his passion and perfection for work is apparently only able to love her when his work is taken from him and he is poisoned and helpless. Apparently he makes the choice to let her poison him. Perhaps he really doesn't want the endless pressure of being a genius after all? It's hard to say, as the screenwriter leaves it a mystery.

Like Whiplash, I recognize great performances and interesting screenplay, but I can't watch it. Who really wants to watch two hours of repulsive people, where the main character is an abusive, horrible person? A little bit of it in a movie adds color. You know that the scriptwriter threw it in for you to not like the abusive character. But, if the whole movie is about an abusive character who doesn't learn the error of his ways, you get the impression that the scriptwriter thinks that we should be entertained by it, or even sympathetic to this toxic white privileged male jerk.

But I wasn't. And I wasn't. I was simply repulsed. And the perfect "solitary genius" who is too important to be bothered with having to be nice to people is a myth.

Loving Vincent: Like a number of other animations I have reviewed, this work is one of astounding, gorgeous animation but also utterly boring. The plot, such as it is, is ... um ... well, there isn't one. A police officer wanders around trying to deliver a letter and asks a few questions about how Van Gogh died. It is all shots, and scenes, and music, and flaccid unimportant dialog. And nothing happens and there are no characters.

Thursday, March 28, 2019

Eye On Kickstarter #61

Welcome to my Eye on Kickstarter series!  This series will highlight Kickstarter campaigns I am following that have recently launched (or I've recently discovered) because they have caught my interest.  Usually they'll catch my interest because they look like great games that I have either backed or would like to back (unfortunately budget doesn't allow me to back everything I'd like to).  But occasionally the campaigns caught my attention for other reasons.  Twice a month, on the 2nd and 4th Fridays, I'll make a new post in this series, highlighting the campaigns that have caught my attention since the last post.  In each post I'll highlight one campaign that has really grabbed my attention, followed by other campaigns I've backed or am interested in.  I'll also include links to any related reviews or interviews I've done.  Comments are welcome, as are suggestions for new campaigns to check out!

You can also see my full Kickstarter Profile to see what I've backed or my old Eye on Kickstarter page that was too unwieldy to maintain.  Also, check out the 2019 Kickstarter Boardgame Projects geeklist over on Board Game Geek for a list of all the tabletop games of the year.
So, without further ado, here are the projects I'm currently watching as of the second Friday of March, 2019:



HIGHLIGHTED CAMPAIGN
Fail Faster: The Playtesting Journal
  • GJJ Games Backed
  • Over the last year I've spend a lot more time refining my own game designs in the hopes that I'll be able to get something published soon. I've done a lot of playtesting, refining, and updating. I've never been very good at taking notes, even in school, so any notes I did jot down for playtests were usually on the pages of rules that I had printed out. As I make changes to the games and need new rules the old ones get tossed, along with my notes. I've been trying to force myself to do a better job of logging the amount of time a game takes, who I play with, etc. but I'm still not as diligent as I should be. Fail Faster: The Playtesting Journal aims to make the whole process of playtesting a game, and in particular tracking data and notes for playtests, a whole lot easier. And easier is definitely something I need. I'm really excited to get my journal and see how well it helps me keep my thoughts and ideas organized.


Designing a board game requires a lot of creativity, but also some discipline when it comes to the most vital part of the process: playtesting your game. The Fail Faster Playtesting Journal will guide you throughout your playtesting process to ensure that you're capturing the right information as well as guide you towards improving your design.

At its core, the Fail Faster Playtesting Journal contains pages to keep track of 36 playtests. The journal is most useful if you dedicate one journal to each game that you are designing, but you could easily use one journal to keep track of all the different games you're designing. Each section has been tested and planned for optimal use of space.





Feudum: Rudders and Ramparts
  • GJJ Games Backed
  • People Behind the Meeples Interview
  • Feudum is by far the heaviest game I own. It's also one of the most beautiful. The artwork and components are absolutely stunning. Now you can add even more stunning components and some additional variation to gameplay with the Rudders and Ramparts expansion.


Graphic Novel Adventures - Season 2
  • I backed the Graphic Novel Adventures last year and, unfortunately, have only gotten to play one so far. However I've had fun with that one and the others look really awesome, too. The artwork and quality is top notch and this second season looks great, too.


Planetoid
  • Palm Island is one of my top games from last year. It's a great solo game that you can play without a table just about anywhere, so it goes with me everywhere. Planetoid also looks like a fun casual game, although it definitely isn't as portable. It's got great table presence though, and a nifty way of flipping up the tiles.


Lord of the Chords
  • My family is very musical. My wife plays piano, violin, cello, dulcimer, and more. My oldest son plays Spanish classical guitar, piano, and is teaching himself French horn. My middle son plays piano, sings, and takes dance. My 20 month old dances to anything with a beat. I play the radio (and poorly according to my wife). Here's a game that we can all come together on though. It's educational, all about music theory, and filled with puns (I've been accused of making a few bad puns from time to time, too).


Throw Throw Burrito
  • This is the next game from The Oatmeal (after Exploding Kittens and Bears vs Babies) and looks to be just as silly. I'm mainly watching this to see just how high it's funding level will go. Currently it's at $1.4 million, so it's not doing quite as well as Exploding Kittens, but still, not too shabby.


Fuzzy Mage Fight
  • People Behind the Meeples Interview 1
  • People Behind the Meeples Interview 2
  • This is the second game from the team that brought you Wanted Earth and it's a huge change from the miniatures heavy combat game. Fuzzy Mage Fight is a battling card game with really awesome artwork. I was scheduled to review this, but unfortunately it didn't work out for my group. We found it to be too unbalanced and it felt unfinished, despite having some interesting mechanics. Even though it wasn't right for us, go check it out and see if it's right for you - it's already funded and knocking out stretch goals.

Battle Of Albuera 1811 - AAR


A big Napoleonic Game with bags of figures on an unfeasibly cramped table was the beginning of my gaming journey nearly 40 years ago and I am so glad to have that back in my locker.

A few months ago I posted a Scenario post for the battle, a combination of my holidays, shift work and illness meant that it took ages to finish, but with a permanent set up and a Yarkshire outlook, there's no need to rush lad.

https://yarkshiregamer.blogspot.com/2018/09/battle-of-albuera-1811-set-up.html


It was also the first real test of my Quarrie version of GdeB and it was a very positive experience, everyone got it straight away. After the game we all agreed they were the way forward and other than a couple of tweeks (some of which were rule based rather than National Characteristics (NC) based).

There were some anti NC comments on the previous post however I find them the most flexible way of representing troop types, for some reason some people can't get past the base stat line, it's a guide, if a particular regiment performed well increase the stats, if it's a Marie Louise battalion reduce them. A link to the original rules post is below.

https://yarkshiregamer.blogspot.com/2018/10/quarrie-to-general-de-brigade.html


Back to the battle itself, things started as you would expect with this battle with a French assault on the Alled right, specifically on the Spanish troops lining a number of hills. As per the scenario the French had 6 moves to "get on with it"

Vistula Legion Lancers make a hole in the Spanish Line
The French Cavalry didn't muck about and went straight at the Spanish Cavalry on the flank, it was no match and it wasn't long before the Spanish Brigade broke, first spoils to the French.

Godinots Brigade advance
In the meantime whilst the British and Portuguese were waiting for the signal to move out the French had redeployed Godinots Brigade to attack the Spanish above Albuera. The remaining French Infantry and Cavalry poured towards the hill line in one seemingly unstoppable wave.

Spanish Infantry open up on the approaching French
With the British troops only just waking up the first Infantry attack fell on the Spanish troops lining the hill. Ripples of musket fire went up and down the line as the French columns came on.

Recule
As you can see from the photo above and the abundance of Falter and Retreat markers the first blood fell to the Spanish who with a combination of steady fire power and poor French die rolling, saw off the initial assault of Godinots Brigade.



The troops of Gazan and Girand where coming into action whilst the French Cavalry continued to cause havoc on the allied right, The Vistula Legion Lancers tried to break the square of the Spanish Irlanda Regt, it was a close run thing but the square held.


After a brief lull the French renewed their attack on the Spanish, with the elite French Grenadier Battalion heading the charge the Spanish finally started to give way after a long hard fight. Brigades began to break and the resistance crumbled.


Coles Division had formed a defensive line with the Fusilier Battalions facing the oncoming French, this was fine whilst the Spanish held but as they left the field the flank of the Fusiliers was exposed. The Allied generals failed to deal with the position and left the flank exposed, leaving the British Cavalry unused on the hill at the rear of Albuera. This would prove their downfall.


Meanwhile the French and British Battalions clashed around the town, a couple of French units made gains but there wasn't enough support to push the advantage home.


The game ended when the French Grenadiers pushed home an attack on the flank of the Fusiliers, poor dice rolling saw the impacted battalion break and then a double 1 on the Brigade morale saw the flank collapse.

There were plenty of untouched British and Portuguese troops to allow an orderly withdrawal from the field but the day and the honours went to the French.

Below is a list of the casualties in our game, if a unit is not mentioned it suffered no losses, these casualties do not include routing troops.

French Casualties

Godinots Brigade
1/16 Legere 13 out of 28 figures = 260 men or 46%
2/16 Legere 16 out of 28 figures = 320 men or 57%
3/16 Legere 6 out of 28 figures = 120 men or 21%
1/51 Ligne 12 out of 36 figures = 240 men or 33%
2/51 Ligne 17 out of 36 figures = 340 men or 47%
3/51 Ligne 5 out of 36 figures = 100 men or 14% Routed
Grenadier Battalion 10 out of 48 figures = 200 men or 21%

Briche Cavalry
10th Hussars 7 out of 20 figures = 140 men or 35% Routed
21st Chasseur 4 out of 20 figures = 80 men or 20%


Brons Cavalry - No Casualties

Bouvier des Èclaits Cavalry
14th Dragoons 1 out of 16 figures = 20 men or 6%
17th Dragoons 1 out of 16 figures = 20 men or 6%

Unattached Cavalry
Vistula Legion Lancers 6 out of 28 figures = 120 men or 21%
27th Chasseur 1 out of 22 figures = 20 men or 5%

Girards Division
2/34 Ligne 3 out of 24 figures = 60 men or 12%
3/34 Ligne 1 out of 24 figures = 20 men or 4%
1/40 Ligne 4 out of 20 figures = 80 men or 20%
2/40 Ligne 1 out of 20 figures = 20 men or 5%

Gazans Division
2/21 Legere 13 out of 20 figures = 260 men or 65%

Werles Division
2/12 Legere 8 figures out of 36 figures = 160 men or 22%
3/12 Legere 4 figures out of 36 figures = 80 men or 11%
3/55 Ligne 2 figures out of 30 figures = 40 men or 7%

Total Casualties 2,700


Allied Casualties 

Colbornes Brigade
2/31st Foot 7 figures out of 21 = 140 men or 33%
2/48th Foot 1 figure out of 23 = 20 men or 4%
2/66th Foot 6 figures out of 22 = 120 men or 27%

Houghtons Brigade
29th Foot 6 figures out of 25 = 120 men or 24%
1/57th Foot 1 figure out of 32 = 20 men or 3%

Abercrombie Brigade
2/28th Foot 4 figures out of 26 = 80 men or 15%

Myers Brigade Broken Brigade
1/7 Fus 14 figures out of 36 = 280 men or 39% Routed 
2/7 Fus 1 figure out of 28 = 20 men or 4%
1/23 Fus 5 figures out of 37 = 100 men or 13%

Harvey's Portuguese Brigade
1/11 Line 1 figure out of 29 = 20 men or 3%
1/23 Line 1 figure out of 28 = 20 men or 4%


Hamilton's Portuguese Brigade
1/2 Line 3 figures out of 30 = 60 men or 10%
1/14 Line 1 figure out of 30 = 20 men or 3%

Blake's Spanish

Lardizabal Brigade
Canaris Foot 1 figure out of 24 = 20 men or 4%
2nd Leon Foot 4 figures out of 24 = 80 men or 17%

Ballasteros Brigade Broken Brigade 
Catalonia Foot 8 figures out of 20 = 160men or 40% Routed 
Pavia Foot 4 figures out of 20 = 80 men or 20%
Lena Foot 7 figures out of 20 = 140 men or 35% Routed 
Castropol Foot 8 figures out of 20 = 160 men or 40 % Routed
Inifiesto Foot 4 figures out of 20 = 80 men or 20%

Zayas Brigade Broken Brigade 
Spanish Guard 12 figures out of 30 = 240 men or 40%
Irlanda Foot 13 figures out of 30 = 260 men or 43% Routed 
Patria Foot 3 figures out of 30 = 60 men or 10%
Toledo Foot 1 figure out of 30 = 20 men or 3%
Esteramdura Foot 3 figures out of 30 = 60 men or 10%
Spanish Artillery 12 figures out of 12 = 240 men or 100%

Loys Spanish Cavalry Brigade Broken Brigade 
Castillo Hussar 5 figures out of 20 = 100 men or 25% Routed 
Granaberos Horse 6 figures out of 20 = 120 men or 30% Routed 

Penne Villemuir Spanish Cavalry Brigade Broken Brigade 
Reina Horse 7 figures out of 20 = 140 men or 35% Routed 

Total Casualties 2980 men

An excellent game, closely balanced and a good challenge for both sides, highly recommended, I will be looking at getting another big Napoleonic Game in soon but this time trying out the rule mods in a 1813 situation.


Explore Simple Game Algorithms With Color Walk: Part 9

Welcome back for more exploration of game algorithms using the simple game Color Walk. In the last post we covered the other fundamental graph search algorithm, depth-first search (DFS), the counterpart to the previously discussed breadth-first search (BFS). These graph algorithms do a full search of the graph of a color walk game, the full set of board positions resulting from each move at each point in the game. We found that running either of these algorithms to completion is extremely prohibitive due to the graph size being exponential in the number of moves. In order to deal with that exponential growth, we need to look at other graph algorithms, and we have quite a few to choose from. We'll explore some categories of graph algorithms and look at one in more detail, Dijkstra's algorithm.

Different Graph Algorithms for Different Questions


Before getting into the algorithms, we should review what makes up a graph and how it relates to the move graph for Color Walk. Most graph algorithms, beyond the basic BFS and DFS, are designed to work on graphs with weighted edges. A weight on an edge means the edge has a value associated with it that can be thought of as a cost of traversing that edge from one vertex to another. A vertex is the same thing as what we've been calling, so far, a node, because we've been talking about the game's move graphs as trees. Internal nodes in a tree are connected by edges and end in leaf nodes. The root node of the move tree is just another vertex, and in the case of a generic graph, any vertex in the graph could potentially be the root node of a corresponding tree. We simply have to pick which vertex we want to use as the root, and the rest of the tree branches out from there. In the case of our move graph, we pick the vertex with the starting board position as the root of the tree.

We can further compare trees and graphs by noticing that a tree is a special type of graph, namely a directed, acyclic graph (DAG). Directed means that edges are traversed in one direction, and in the move graph that direction is from vertices corresponding to earlier moves to vertices corresponding to later moves. More precisely, the vertices are the board positions that are arrived at for each move, and the edges represent the moves that change one board position into another board position by removing blocks.

Acyclic means that a vertex cannot be revisited by following some finite number of edges without backtracking (since the DAG has directed edges, we can't backtrack anyway). The move graph isn't quite acyclic because each vertex has an edge to itself for the same move as the move that results in that board position. Some vertexes also have edges that come back to themselves because the corresponding move doesn't remove any blocks, resulting in the same board position. These cycles can easily be detected and eliminated, as we saw in the BFS and DFS algorithms, so the move tree can be thought of as a DAG, even if it isn't in the strictest sense, by removing these cyclic edges.

Returning to the idea of edge weights, most graph algorithms work by optimizing the cost of traversing edges by their weights. A path consisting of the lowest sum of weights is considered the best path, and graph algorithms will work to find those paths. We have already been assigning weights to the edges in our greedy algorithms. We called them heuristics instead of weights, but they amount to the same thing. The heuristic values associated with each move can be considered the weights assigned to each corresponding edge in the graph. Different heuristics are different weight functions. For example, in the basic greedy algorithm the heuristic was the number of blocks removed on a given move. The number of blocks removed would be the weight of the edge corresponding to that move. So far all of the weights we've used have been positive, but it is feasible to have negative weights on graph edges as well. Some graph algorithms will work with negative weights, while others require all positive (or all negative) weights.

Graph algorithms can be classified into four different types, based on what they solve for a given graph. Minimum spanning tree algorithms will find the minimum set of edges, taking weights into account, that connects all of the nodes in the graph. Basically, these algorithms remove the most costly and unnecessary edges from the graph to create a tree still containing all vertices from the original graph. Since our move graph is already a tree and we're interested in finding the minimum path from one vertex to another, minimum spanning tree algorithms won't be too useful for us, but they do solve a large class of problems, including automatic routers for circuit board or integrated circuit layouts, for example.

The shortest paths algorithms are the ones we're most interested in. These algorithms find the lowest-cost path from a source vertex to all other vertices in the graph. It is interesting that solving this problem is asymptotically as fast as finding the shortest path between two specific nodes, but we are working with an enormous graph, so we'll have to make some modifications to Dijkstra's algorithm, the shortest path algorithm we'll use, to make it tractable for the move graphs. Part of that modification will be stopping early when we find the shortest path to the end vertex we're looking for.

Another type of algorithm that's similar to the shortest paths algorithms is the all-pairs shortest paths algorithm. These algorithms will efficiently find the shortest paths between all pairs of vertices in a graph. This problem seems much larger than the single-source shortest path problem, but it can actually be solved faster than iterating through every vertex and running Dijkstra's algorithm. We don't need to do this for our problem, so we won't be looking into this type of algorithm here.

The last type is the maximum flow algorithms. These algorithms take a pair of vertices and find the maximum rate that something can move through the graph from one vertex to the other without overflowing any of the weights in the graph. The weights can be thought of as capacities for each edge between vertices, and this type of problem has all kinds of applications such as electricity in wires, liquids in pipes, traffic flow, assembly lines, and much more. Yet, it's not useful for our immediate problem, although it's good to know that these algorithms exist.

Single-Source Shortest Path Algorithms


As described just a moment ago, single-source shortest path algorithms will find the shortest path from a source vertex to all other vertices in the graph. Let's ignore for the moment that this is a colossal problem for our move graphs, with well over 440 vertices for most boards even after trimming out all cyclical edges. Instead, think about what the graph looks like. It's a tree with a single root node, our source vertex, that spreads out at each level by a factor of four.

At some point the branches in the exponentially expanding tree will start reaching leaf nodes, but these leaf nodes are, in fact, all the same vertex—an empty board. That means at some point every branching path in the tree will end up at the same vertex with an enormous number of edges coming into it, and we want to find the one that comes from the path through the least number of vertices. This is a potentially simplifying insight that we'll have to keep in mind. Take the example sub-graph pictured below as an example, where there are three colors to choose from for moves, and each vertex is labeled with its move number. Eventually, every path of moves ends in the same place, at the end vertex.

Example move graph with three colors and an end node

The most straightforward way to find this path is to use the Bellman-Ford algorithm. This algorithm will sweep through every vertex in the graph, and for each vertex it will take each edge in the graph and relax it. You see, each edge has a source vertex, where the edge comes from, and a sink vertex, where the edge goes to. Each vertex will also have a distance associated with it that starts at infinity, unless it is the overall source vertex where the path starts, in which case the distance is zero. Relaxing an edge means that we compare the distance of the sink vertex with the distance of the source vertex plus the edge weight. If the sink distance is more, then the sink distance will be updated to the source distance plus the edge weight. The pseudo-JavaScript code for the Bellman-Ford algorithm looks like this:
function BellmanFord(graph) {
_.each(graph.vertices, function(vertex) {
_.each(graph.edges, function(edge) {
relax(edge);
});
});
}

function relax(edge) {
if (edge.sink.distance > edge.source.distance + edge.weight) {
edge.sink.distance = edge.source.distance + edge.weight;
edge.sink.previous = edge.source;
}
}
This code makes some assumptions about the graph's data structure, namely that it has a list of vertices and edges, and each edge has properties for its source and sink vertices and weight. Vertices have properties for their distance and a link to the previous vertex that is on the currently found shortest path. A proof of the correctness of this algorithm is a bit too involved to get into here, but essentially, it relaxes every edge in the graph for every vertex in the graph so that the calculated distances are guaranteed to fully propagate through the graph. The result is that each vertex will have its shortest distance to the source vertex, and a link to the previous vertex in its shortest path.

This algorithm is dead simple, but also completely unworkable for our problem for two reasons. First, it requires us to generate and store the entire move graph before running the algorithm. This task has already been shown to be quite beyond the ability of any computer for the foreseeable future. Second, we have to run relax(edge) for every edge in the graph, and do that full sweep of edges for every vertex in the graph. In other words, this algorithm is O(V2) where V is the number of vertices. Such a processing feat is never going to happen. We need to find a better way.

One thing we should notice is that the Bellman-Ford algorithm is doing a ton of extra work to propagate distances through the graph. Most vertex distances will not change on any particular sweep of the edges because the distances around them haven't changed. The algorithm was designed to work with any type of graph and tolerate cycles, but the move graph has the added restriction of being a DAG. Using that restriction, we can improve the algorithm by traversing the graph in breadth-first order while relaxing edges.
function dagShortestPaths(graph) {
var vertices = new Queue();
vertices.enqueue(graph.root);
while (vertices.getLength() > 0) {
var vertex = vertices.dequeue();
_.each(vertex.edges, function(edge) {
relax(edge);
vertices.enqueue(edge.sink);
});
}
}
The relax() function is the same as with Bellman-Ford. With this improvement, we're doing much less work, while propagating vertex distances in a way that ensures that vertices are updated quickly and without a lot of extra waste. In the case of our move graph, where vertices nearly always have one incoming edge, the running time will be O(V).

This algorithm is a great improvement over Bellman-Ford, but we've run into a somewhat silly issue. This algorithm is basically BFS with edge weights added into the mix. Because edge weights are just an additional metric in the move graph and not a strict cost of traversing the edges, they become meaningless, and the algorithm will perform no better than BFS. It should be obvious that it would take at least as long to run, and if we allow it to run over the entire graph as defined, much longer. Remember, BFS stopped as soon as it found the empty board node.

This DAG shortest paths algorithm is great for smaller DAGs than what we're working with, and with DAGs that have true edge weights instead of weights that we're just using as heuristics. What we need is an algorithm that uses the edge weights in a way that dramatically reduces the number of vertices visited before the destination node is visited, and for that we need Dijkstra's algorithm.

Dijkstra's Algorithm


To implement Dijkstra's algorithm for the Color Walk move graph, we're going to need to revisit the the heuristics we would use for edge weights. Simply using the number of blocks removed for each edge (move) probably won't be good enough, but to see why, let's first look at an outline of the algorithm.
function Dijkstra(graph)
var vertices = new Queue();
vertices.enqueue(graph.root);
while(vertices.getLength() > 0) {
var vertex = vertices.extractMin();
_.each(vertex.edges, function(edge) {
relax(edge);
vertices.enqueue(edge.sink);
});
}
}
Waaait a minute! This algorithm looks almost exactly like the DAG shortest paths algorithm, which looks almost exactly like BFS. What gives? In truth, it is very similar to both of those algorithms. The key difference here is that we're not pulling the vertices out of the queue in the same order that we're adding them in. We're pulling out the vertex with the minimum distance to the source vertex of all the vertices in the queue with vertices.extractMin(). That means the queue is actually a priority queue of some kind. That means that we're efficiently prioritizing which path we're looking at each time we look at a new vertex. That means we need to make sure we're prioritizing the vertices with the right weight function.

When we were searching for the empty board node with BFS, we were searching in move order, meaning we searched all first moves before searching all second moves, before searching all third moves, and so on. Now with Dijkstra's algorithm, we could be searching moves out-of-order. We could be headed down a promising path on the twelfth move when the next vertex pulled out of the priority queue is actually for the tenth move because the previous 12-move path has gotten too long, and there are shorter paths with less moves at the top of the queue. We want to capture the property that the shortest path is the one with the least number of moves, but balance that with the idea that moves that remove more blocks are likely to be on the shortest path.

The problem with simply combining the move number for a vertex and the number of blocks removed for that vertex is that we want to minimize the former and maximize the latter. We can't mix the two goals. We need to pick either minimization or maximization for the priority queue to work. It doesn't much matter which way we choose, so we'll stick with minimization and make the values for number of blocks removed negative. Thus, the weight for any given edge is

weight = 1 - blocks_removed_on_move

This equation is true because each move will increase the number of moves by 1 and remove a certain number of blocks. To calculate the distance associated with a new vertex, v, we add the weight to the distance of the previous vertex, u:

distancev = distanceu + weightu,v

We can simplify this equation by noticing that the distance to any vertex is simply the accumulation of moves minus the accumulation of blocks removed, or:

distancev = move_number - blocks_removed

With that worked out, we can start implementing our version of Dijkstra's algorithm for Color Walk. First, we add the algorithm to the list of choices in the HTML input element and to the switch statement:
  function Solver() {
// ...

this.init = function() {
// ...

$('#solver_type').change(function () {
switch (this.value) {
// ...
case 'dijkstra':
that.solverType = that.dijkstra;
that.metric = areaCount;
break;
default:
that.solverType = that.roundRobin;
break;
}

// ...
});

// ...
};
Then we need to fill in the algorithm function, which is similar to the BFS algorithm, but with a priority queue instead of a regular queue and some changes to the limit checking on the size of the queue:
    this.dijkstra = function() {
var vertices = new PriorityQueue({ comparator: function(a, b) { return a.cost - b.cost } });
vertices = addVertices(vertices, 1, null, blocks[0].cluster.blocks.length);

while (vertices.length > 0) {
var vertex = vertices.dequeue();
markers = vertex.markers;

if (vertices.length > 250000) {
doMarkedMoves();
vertices.clear();
} else {
vertices = addVertices(vertices, vertex.depth + 1, vertex.control, vertex.cleared);
}

vertex.markers = null;
}
}
This code follows the outline of the pseudocode presented above fairly closely. It creates a priority queue, adds the first vertex, and then loops through vertices, pulling the vertex with the minimum cost (or distance, they're interchangeable) out of the queue each time and adding its child vertices to the queue inside addVertices(). I looked around for a JavaScript priority queue to use for this task, and found a nice one with a clean API. When creating the queue, you need to provide a comparator function so that it knows how to compare the value of nodes in the queue and maintain its priority requirement. The cost properties are an additional property on the vertices that's calculated inside addVertices().

Because the vertices don't stay in inserted order, and we need to know the cost of vertices before adding them to the queue, we need to run checkGameBoard() on each vertex in addVertices(). (Check out this previous post on BFS for details on how it was implemented before.) This change simplifies the above function a bit, and other than what's already been described, we only need to make sure the queue doesn't get too big. If it reaches too big of a size, we're going to forget adding more vertices, do the moves corresponding to the current minimum vertex, clear the queue, and bail out. We'll come around again at the new move number and partially cleared board to try again to find the end-of-game vertex. Some boards will have so many similarly weighted paths that this tactic is necessary, otherwise the queue will get too large and cause a crash. Surprisingly, this doesn't happen too often, and the algorithm will be able to complete the search on most boards in a single sweep.

Now let's look at what's going on in addVertices(). The idea is simple. This function needs to run through all of the controls, checking to see how many blocks each control removes, calculating the cost of each of these new vertices, and adding the vertices to the queue. If it runs into the end-of-game vertex, it should stop. Here's what it looks like:
    function addVertices(vertices, depth, prev_control, prev_cleared) {
var stop = false;
_.each(controls, function (control) {
if (control !== prev_control && !stop) {
var removed_blocks = control.checkGameBoard(depth, areaCount);

if (endOfGame()) {
doMarkedMoves();
vertices.clear();
stop = true;
} else if (removed_blocks - prev_cleared > 0) {
var markers_dup = markers.slice();
var cost = max_moves*depth - removed_blocks;
if (removed_blocks > 590) cost -= (max_moves - 5)*depth;
vertices.queue({markers: markers_dup,
depth: depth,
control: control,
cost: cost,
cleared: removed_blocks});
}
}
});
While the concept of the function is simple, the implementation has a number of tricky details. I had a pretty rough time getting this code right. It tripped me up more times than I care to admit, but let's go through and look at each detail anyway. Starting at the top, we need a stop flag to know when we've found the end-of-game and need to stop searching. If we only did the moves and cleared out the queue, we may have found the end while having more controls to loop through, and the each() function would go on its merry way, adding more vertices to the recently emptied queue. The algorithm wouldn't actually stop when it was supposed to, so we need the flag to make sure we ignore any leftover controls after finding the end-of-game vertex.

Next, the check to make sure at least one block was removed on the current move before adding the new vertex to the queue needed to be correct. The correct calculation is the difference between the removed blocks after the move and those blocks that were cleared before that move, because areaCount() counts all of the marked blocks in markers, not just the ones marked on the current move. Therefore, I needed to pass prev_cleared, the number of previously cleared blocks, into addVertices() from the parent vertex, which means I needed to store the number of blocks removed on a move in that move's vertex for this whole calculation to work.

Another subtle point is that with vertices being pulled out of the queue in a different order than they were inserted, each set of markers needed to be copied instead of sharing the same copy among all of the child vertices from any given parent vertex. That means the markers.slice() line needed to get moved inside the each() loop.

Then, the basic cost function of move_number - blocks_removed didn't work too well. Why that is has to do with the scale of those two values and how they work together. Imagine getting rid of either one of them. If the cost function was only move_number, then every vertex with a smaller move number would be pulled out of the priority queue before any vertex with a larger move number. Dijkstra's algorithm would reduce to BFS in that case. If, on the other hand, the cost function was only -blocks_removed, then the vertex with the most blocks removed would always be pulled out of the queue first, reducing the algorithm to the greedy algorithm.

These three possible cost functions all lie on a continuum, with BFS on one end, the greedy algorithm on the other end, and move_number - blocks_removed somewhere in the middle. But move_number - blocks_removed is not the only intermediate option. Consider that move_number is on the order of 30-40 moves, and blocks_removed will always end in 600 for a 30x20 block board. The move_number has much less weight than blocks_removed, but we can add a scale factor to it. This scale factor is actually necessary to get good performance because otherwise it's possible, and indeed likely, that the minimum vertex pulled out of the queue at some point during the search will clear out a dozen or more blocks and end the game, but be several moves more than the minimum number of moves. We want to add weight to move_number, so we can use max_moves from the UI input as the scale factor for move_number (represented in the code as depth).

With the correct scale factor—found to be around 25—the performance of the algorithm is much better, but it then hits another snag. Near the end of the search, the algorithm hits a wall and starts churning on all of the other possibilities in the queue because the move_number gets larger than blocks_removed on the vertices closest to the end-of-game vertex. The algorithm kind of devolves into BFS again, and it would take forever backtracking to explore older paths in its history unless we can find a way of forcing it to choose the vertices close to the finish line. To force this behavior, if we're within 10 blocks of finishing, we'll reduce the scale factor to bump the priority of those vertices. Since we're within 10 blocks of finishing, there are likely only a few colors of blocks left, and we can move more towards the greedy algorithm on the spectrum to finish quickly.

After getting all of these little, important details right, we can finally run a version of Dijkstra's algorithm that will run to completion without crashing and, hopefully, find some good solutions to the game boards. Let's see what happens when we run 100 iterations of this algorithm.

Dijkstra's Algorithm Results

We should keep in mind when looking at these results that the version of Dijkstra's algorithm that we're using is not the complete algorithm. We're intentionally stopping early when we find the first end-of-game vertex because if we let it run to completion, it would take an eternity to run, and in its current form would always run out of memory and crash. Taking that into account, here are the results with a move scale factor of 25:

100 iterations of Color Walk with Dijkstra's Algorithm

That result seems pretty good. How does it stack up to the other algorithms?

AlgorithmMinMeanMaxStdev
RR with Skipping 37 46.9 59 4.1
Random with Skipping 43 53.1 64 4.5
Greedy 31 39.8 48 3.5
Greedy Look-Ahead-2 28 37.0 45 3.1
Greedy Look-Ahead-5 25 33.1 41 2.8
Max Perimeter 29 37.4 44 3.2
Max Perimeter Look-Ahead-2 27 35.0 44 2.8
Perimeter-Area Hybrid 31 39.0 49 3.8
Deep-Path 51 74.8 104 9.4
Path-Area Hybrid 35 44.2 54 3.5
Path-Area Hybrid Look-Ahead-4 32 38.7 45 2.7
BFS with Greedy Look-Ahead-5 26 32.7 40 2.8
DFS with Greedy Look-Ahead-5 25 34.8 43 3.9
Dijkstra's Algorithm 29 33.1 40 1.9

Well, the minimum number of moves for Dijkstra's algorithm was bested by GLA, BFS, and DFS, but the mean was only barely bested by BFS and the maximum was equal to the previous best, BFS. Look at the standard deviation, though. Dijkstra's algorithm gives consistently good solutions by a significant margin. The next best algorithm for giving consistent results is the deep path-area hybrid algorithm with look-ahead by 4, and that one performs 5.6 moves worse on average.

Dijkstra's algorithm definitely has some nice characteristics, but why doesn't it perform the best in all cases? The main reason is because of what was mentioned earlier: we're not running the algorithm to completion. Cutting it off early means that there are still potentially shorter paths in the priority queue that could be explored, but we stop searching the first time we find the end-of-game vertex. The weight function also plays a role here because we're trying to play a balancing act between optimizing the primary goal—the number of moves—and the secondary goal that helps focus the search—the number of blocks removed. If we increased the scale factor to add more weight to the number of moves, the search will take much longer, and it will run out of memory for the growing priority queue more often, requiring the algorithm to commit to some number of moves for the last minimum vertex it pulls out of the queue and start again from that point.

Part of what makes Dijkstra's algorithm so consistently effective is that it is another form of a greedy algorithm, but it keeps track of other promising paths while it pursues what looks like the best option at every moment. Each time through the while loop, it's looking at the current best possible next vertex in the path, and when the child vertices of that vertex are added to the queue, the next best vertex may not be one of those just added, but a vertex from a different promising path stored in the queue. The algorithm will remember all of the other paths it could take, and once the current path gets too expensive, it will switch to a cheaper one until that one also gets too expensive. This constant development of numerous good options for the shortest path turns out to be a very efficient way to find one that's quite short, if not the shortest.

Given the potential of Dijkstra's algorithm, we're not quite done exploring it. While implementing it, some options became apparent for making it perform better. We could look at another hybrid approach with the greedy algorithm, either running the greedy algorithm before or after Dijkstra's algorithm, or we could try running Dijkstra's algorithm twice—once to half the blocks removed and again to complete the game. Much experimentation is possible here, combined with varying the scale factor, to see if we can push Dijkstra's algorithm to beat GLA-5. We'll explore those options next time.


Article Index
Part 1: Introduction & Setup
Part 2: Tooling & Round-Robin
Part 3: Random & Skipping
Part 4: The Greedy Algorithm
Part 5: Greedy Look Ahead
Part 6: Heuristics & Hybrids
Part 7: Breadth-First Search
Part 8: Depth-First Search
Part 9: Dijkstra's Algorithm
Part 10: Dijkstra's Hybrids
Part 11: Priority Queues
Part 12: Summary