and has 1 comment
Well, it's pretty obvious, but I wanted to post it here, as well. You see, we have this query that was supposed to filter some values based on a parameter. The query was done like this: SELECT * FROM table WHERE value=(CASE WHEN @filter IS NULL THEN value ELSE @filter). Can you spot the problem? Indeed, if value is NULL, then value is NOT equal to value. Not only is this incorrect, but also bad from the standpoint of the SQL execution plan. It is much faster to do SELECT * FROM table WHERE (@filter is NULL OR value=@filter). If, for whatever reason, you need the first syntax, you need to do it like this: SELECT * FROM table WHERE ISNULL(value,@impossibleValueThatIsNotNull)=COALESCE(@filter, value, @impossibleValueThatIsNotNull). Yeah, a bit of a show off, but when the "no filter" value is null, it's better to use ISNULL and COALESCE wherever possible.

I was just thinking about Coma a few days ago. I don't know why. I thought I miss one of their beautiful songs. And here I see on YouTube they released a new video just when I was thinking of them. This one is a very nice combination of Catalin's lyrics, melodic and hard sounds and a cool interweave of the voices of Catalin and Dan - it's not the usual contrast between singing and shouting, but rather a vocal collaboration which works surprisingly well. Without further ado, here it is.
Chip, by Coma:
\

Also, if you want to see a live version:

I have at work a very annoying HTTP proxy that requires a basic authentication. This translates in very inconsistent behaviour between applications and the annoying necessity of entering the username and password whenever the system wants it. So I've decided to add another local proxy to the chain that handles the authentication for me forever.

This isn't as easy as it sounds. Sure, proxies are a dime a dozen, but for some reason most of them seem to be coming from the Linux world. That is really bad user interaction, vague documentation and unhelpful forums where any request for help ends up in some version of "read the fucking manual". Hence I've decided to help out by creating this lovely post that explains how you can achieve the purpose described above with very little headache. These are the very easy steps that you have to undertake:
  1. Download and install Privoxy
  2. Go to the Program Files folder and look for Privoxy. You will need to edit two files: config.txt and user.action
  3. Optional: change the listen-address port, otherwise the proxy will function on port 8118
  4. Enter your proxy authentication username and password in the fields below and press Help me configure Privoxy - this is strictly a client base Javascript so don't worry that I am going to steal your proxy credentials...
  5. Edit user.action and add the bit of text that appeared as destined for that file.
  6. Edit config.txt, look for examples of forward and add to it the bit that belongs to config.txt and replace proxy:port and the domains and IP masks with the correct values for you
  7. Restart Privoxy
  8. Configure your internet settings to use a proxy on 127.0.0.1 and the port you configured in step 2 (or the default 8118)

This should be it. Enjoy!

Username:

Password:





I made a function in T-SQL that parsed some string and returned a decimal. It all worked fine until one of my colleagues wanted to use it on the test server. And here there was, a beautiful error message: 'decimal' is not a recognized built-in function name. I isolated the line, executed it, same error. It was like the server did not understand decimals anymore. The line in question was a simple SELECT TRY_CONVERT(DECIMAL(18,6),'10.33'). If I used CONVERT, though, it all worked fine. Another hint was that the function worked perfectly fine on the same server, in another database. The problem was that for that particular database, the defined SQL server version was 2008, not 2012. We changed it and it all worked fine after that. The setting in question is found in the Properties of the database, Options, Compatibility level.

While working on a small personal project, I decided to make a graphical tool that displayed a list of items in a Canvas. After making it work (for details go here), I've decided to make the items animate when changing their position. In my mind it had to be a simple solution, akin to jQuery animate or something like that; it was not.

The final solution was to finally give up on a generic method for this and switch to the trusted attached properties. But if you are curious to see what else I tried and how ugly it got, read it here:
Click here to get ugly!

Well, long story short: attached properties. I created two attached properties CanvasLeft and CanvasTop. When they change, I animate the real properties and, at the end of the animation, I set the value. Here is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace Siderite.AttachedProperties
{
public static class UIElementProperties
{
public static readonly DependencyProperty CanvasLeftProperty = DependencyProperty.RegisterAttached("CanvasLeft", typeof(double), typeof(UIElementProperties), new FrameworkPropertyMetadata(
0.0,
FrameworkPropertyMetadataOptions.OverridesInheritanceBehavior,
CanvasLeftChanged));

[AttachedPropertyBrowsableForType(typeof(UIElement))]
public static double GetCanvasLeft(DependencyObject element)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
return (double)element.GetValue(CanvasLeftProperty);
}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public static void SetCanvasLeft(DependencyObject element, double value)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
element.SetValue(CanvasLeftProperty, value);
}

private static void CanvasLeftChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var sb = new Storyboard();
var oldVal = (double)e.OldValue;
if (double.IsNaN(oldVal)) oldVal = 0;
var newVal = (double)e.NewValue;
if (double.IsNaN(newVal)) newVal = oldVal;
var anim = new DoubleAnimation
{
From = oldVal,
To = newVal,
Duration = new Duration(TimeSpan.FromSeconds(1)),
FillBehavior = FillBehavior.Stop
};
Storyboard.SetTarget(anim, d);
Storyboard.SetTargetProperty(anim, new PropertyPath("(Canvas.Left)"));
sb.Children.Add(anim);
sb.Completed += (s, ev) =>
{
d.SetValue(Canvas.LeftProperty, newVal);
};
var fe = d as FrameworkElement;
if (fe != null)
{
sb.Begin(fe, HandoffBehavior.Compose);
return;
}
var fce = d as FrameworkContentElement;
if (fce != null)
{
sb.Begin(fce, HandoffBehavior.Compose);
return;
}
sb.Begin();
}


public static readonly DependencyProperty CanvasTopProperty = DependencyProperty.RegisterAttached("CanvasTop", typeof(double), typeof(UIElementProperties), new FrameworkPropertyMetadata(
0.0,
FrameworkPropertyMetadataOptions.OverridesInheritanceBehavior,
CanvasTopChanged));

[AttachedPropertyBrowsableForType(typeof(UIElement))]
public static double GetCanvasTop(DependencyObject element)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
return (double)element.GetValue(CanvasTopProperty);
}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public static void SetCanvasTop(DependencyObject element, double value)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
element.SetValue(CanvasTopProperty, value);
}

private static void CanvasTopChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var sb = new Storyboard();
var oldVal = (double)e.OldValue;
if (double.IsNaN(oldVal)) oldVal = 0;
var newVal = (double)e.NewValue;
if (double.IsNaN(newVal)) newVal = oldVal;
var anim = new DoubleAnimation
{
From = oldVal,
To = newVal,
Duration = new Duration(TimeSpan.FromSeconds(1)),
FillBehavior = FillBehavior.Stop
};
Storyboard.SetTarget(anim, d);
Storyboard.SetTargetProperty(anim, new PropertyPath("(Canvas.Top)"));
sb.Children.Add(anim);
sb.Completed += (s, ev) =>
{
d.SetValue(Canvas.TopProperty, newVal);
};
var fe = d as FrameworkElement;
if (fe != null)
{
sb.Begin(fe, HandoffBehavior.Compose);
return;
}
var fce = d as FrameworkContentElement;
if (fce != null)
{
sb.Begin(fce, HandoffBehavior.Compose);
return;
}
sb.Begin();
}
}
}

and this is how you would use them:

<ListView ItemsSource="{Binding KernelItems}" 
SelectedItem="{Binding SelectedItem,Mode=TwoWay}"
SelectionMode="Single"
>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Black" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="att:UIElementProperties.CanvasLeft" >
<Setter.Value>
<MultiBinding Converter="{StaticResource CoordinateConverter}">
<Binding Path="X"/>
<Binding Path="ActualWidth" ElementName="lvKernelItems"/>
<Binding Path="DataContext.Zoom" RelativeSource="{RelativeSource AncestorType={x:Type Window}}"/>
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="att:UIElementProperties.CanvasTop" >
<Setter.Value>
<MultiBinding Converter="{StaticResource CoordinateConverter}">
<Binding Path="Y"/>
<Binding Path="ActualHeight" ElementName="lvKernelItems"/>
<Binding Path="DataContext.Zoom" RelativeSource="{RelativeSource AncestorType={x:Type Window}}"/>
</MultiBinding>
</Setter.Value>
</Setter>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Cyan"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" Color="White" Opacity="0.5" BlurRadius="10"/>
</Setter.Value>
</Setter>
<Setter Property="Canvas.ZIndex" Value="1000"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>

Hope it helps.

I've reached the last of the animes in the Studio Ghibli series that I wanted to watch (again) and it was nice that this one got to be the final one. You see, before that I had watched The Cat Returns and I rated it mediocre, so unlike the beautiful movies from the same collection. Whisper of the Heart seems to be the film designed to redeem it.

The story is that of a young girl who likes to read a lot of books. She notices that most of the books that she borrowed from the library had the same name on their library cards, a boy that she didn't know. Coincidentally she follows a fat cat, apparently named Muta, to the shop of an old man who has a beautiful doll of a cat in a suit: the Baron of Gikkingen. You guessed it, two characters from The Cat Returns. And behold, the old man is the grandfather of the boy that kept borrowing the same books.

Whisper of the Heart seems to just take beautiful elements from other Ghibli animes and bring them all together in a wonderful union. The windy hills of Tokyo, which still has beauty despite the expansion of the city. The young girl who is not only smart and sensible, but also ambitious and kind. The family who is sometimes annoying and overbearing, but that in the end is the source of support for the development of the child it nurtures. The indolent fat cat :)

And then the love story, something that springs from common interests and a karmic connection between two people who seem to have been meant for each other. But there is more. They don't just click and that's it; they get motivated and energized to be the best of what they can be in order to honor the relationship in which they enter. In a way, it is a continuation of the warm and supporting family model from which both protagonists come.

One of the scenes in the anime was so funny to my wife that she spoke the Japanese words from it for a week. What a wonderful thing to have a film that not only makes me want to be a better man, but that already does make me be so by connecting me stronger to the one I love. And I watched it on Valentine's day, too! How can I rate it any less than with a perfect 10?

Returning to The Cat Returns, it somehow felt to me that the story linked to it also from the perspective of the ever aspiring artist; the rough and unpolished plot there sounds a lot like the story Shizuku writes, her first but one in many, the stone that will allow her to get to the skill and experience to do this story, which is so much better and complete. It does seem that way to me, since I watched The Cat Returns first, but chronologically Whisper of the Heart was made seven years earlier.

Now I don't know exactly in which proportion is Hayao Miyazaki responsible for the great quality of this film and story and how much Hiiragi Aoi, the writer of the original manga, but I heartily recommend the end result. I may be exaggerating, but this could be the best anime Studio Ghibli ever did, and that is saying much.

For a WPF project I wanted to create a graphical representation of a list of items. I computed some X,Y coordinates for each item and started changing the XAML of a Listview in order to reflect the position of each item on a Canvas. Well, it is just as easy as you imagine: change the ItemsPanel property to a Canvas and then style each item as whatever you want. The gotcha comes when trying to set the coordinates. The thing is that for each item in a listview a container is constructed and inside the item template is displayed. So here you have all you items displayed exactly as you want them, except the coordinates don't work, since what needs to be placed on the Canvas are the generated containers, not the items. Here is the solution:
<Window.Resources>
<local:CoordinateConverter x:Key="CoordinateConverter"/>
<DataTemplate DataType="{x:Type vm:KernelItem}"> <!-- the template for the data items -->
<Grid>
<Ellipse Fill="{Binding Background}" Width="100" Height="100" Stroke="DarkGray" Name="ellipse"
ToolTip="{Binding Tooltip}"/>
<TextBlock Text="{Binding Text}" MaxWidth="75" MaxHeight="75"
HorizontalAlignment="Center" VerticalAlignment="Center"
TextAlignment="Center"
TextWrapping="Wrap"
ToolTip="{Binding Tooltip}" />
</Grid>
</DataTemplate>
</Window.Resources>
<ListView ItemsSource="{Binding KernelItems}" Name="lvKernelItems"
SelectedItem="{Binding SelectedItem,Mode=TwoWay}"
SelectionMode="Single"
>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Black" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/><!-- no highlight of selected items -->
<Setter Property="Foreground" Value="White"/>
<Setter Property="(Canvas.Left)" >
<Setter.Value>
<MultiBinding Converter="{StaticResource CoordinateConverter}">
<Binding Path="X"/>
<Binding Path="ActualWidth" ElementName="lvKernelItems"/>
<Binding Path="DataContext.Zoom" RelativeSource="{RelativeSource AncestorType={x:Type Window}}"/>
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="(Canvas.Top)" >
<Setter.Value>
<MultiBinding Converter="{StaticResource CoordinateConverter}">
<Binding Path="Y"/>
<Binding Path="ActualHeight" ElementName="lvKernelItems"/>
<Binding Path="DataContext.Zoom" RelativeSource="{RelativeSource AncestorType={x:Type Window}}"/>
</MultiBinding>
</Setter.Value>
</Setter>
<Style.Resources><!-- no highlight of selected items -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True"><!-- custom selected item template -->
<Setter Property="Foreground" Value="Cyan"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" Color="White" Opacity="0.5" BlurRadius="10"/>
</Setter.Value>
</Setter>
<Setter Property="Canvas.ZIndex" Value="1000"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>

As a bonus, you see the way to remove the default selection of an item: the ugly dotted line and the highlighting background.

I can't say that Neko no ongaeshi had a great effect on me. The animation was OK, the story was like a fairy tale, but it lacked something, a special feeling that I was expecting to have.

The plot is that a young girl saves a cat from death and finds herself uncomfortably rewarded by the entire hidden nation of cats with a trip to their kingdom, a marriage to their prince and a free transformation into a feline. She doesn't want this, but helped by new friends, she manages to escape. I am not really spoiling anything here. It wasn't like at any moment I felt that she might be in real danger, which I think was the biggest flaw of the story. Another anime from Studio Ghibli, Spirited Away, features a much more beautiful and scary foray in a magical world and one of the novels of Clive Barker, The Thief of Always, brings the required tension and fear that is missing in this film.

Another issue I had with this is that, other than eat mice and fish, the cats behaved exactly like humans, missing entire opportunities to delight the viewer with so many catty things. They don't use their claws, they don't do acrobatics, they live in a feudal community and are loyal to each other. The whole concept of a feline kingdom passed right by the creators of the anime.

My conclusion is that this is a film for very little children or a lazily made one. It's not that I didn't enjoy watching it, but was completely bland, devoid of any inspiration that would make it rise above average.

I always liked animes from Studio Ghibli., but until now I didn't quite get why. It is because they have calm. Everything today has to be over the top, flashy, fast. Ghibli stories take their time, they feature normal people with normal desires and rhythms. behaving normally.

The Ocean Waves is about a cute girl moving from Tokyo to a provincial highschool in Kochi. Everybody is curious about her, but she is a loner and quite rude. Two friends are both interacting with her, but it's never clear what's in their hearts. Slowly, but surely, we start to understand each of the actors and the story comes full circle after graduation, at the first highschool reunion.

I've learned so much about Japanese culture from animes, but the ones from Ghibli make me understand the people. The stories often have what is missing in not only animation, but real actor movies as well: people that you can empathise with, because they are like you (or rather, like you would like to be, but not in infantile fantasies, but in your hopeful dreams).

Really nice movie, it certainly worth seeing.

When I first started watching the movie and I saw the way it was drawn - colored pencil style, I thought it is some sort of children thing and I would not like it. But the minimalistic animation works very well for this film, which shows the everyday life of a Japanese family. They are not very smart, good looking or have anything special. They are forgetful, self centered and lazy. But they have each other and they are happy. That's a beautiful message in a world dominated by heroes, celebrity and egotism.

One might not like one thing, that the story is merely descriptive. There is no "end" to it, just a funny enumeration of family moments. I enjoyed it, though. The speech at the beginning, from the woman advising the newly weds what life is and how they should spend it together is both funny, mostly true and descriptive of the rest of the film. The part with "life is hard when you are alone, but even two losers can go through life if they are together" cracked me up, as well as the part with "have children, it will help you appreciate your parents; they will come and take care of them for you from time to time".

The bottom line is that this is a movie that families should watch together. It would relieve the pressure of never appearing to make mistakes, trying to be a perfect whatever and missing the joy of life. Now, it's too late for my family, but this film may be a way to screw up your children less.

So, while this would not be for everyone, The Yamadas is one of those Studio Ghibli. animes that makes you have warm feelings.

A lot of people nowadays are born in the city or a large town somewhere; nature and animal life is something you see on TV. Few older people, though, may remember what life used to be mere decades ago, when wild nature was what awaited you when you got out of your yard and people were three times fewer.

Pom Poko is a movie about the changes urban development brings to the land, as seen from the perspective of a playful and intelligent race of racoons, magically endowed with the ability to shapeshift into anything they choose. Worried, scared and finally enraged by the destruction of their home forests by the expansion of Tokyo, they decide to fight back. Alas, their efforts are in vain, there is no stopping the humans.

A beautiful anime, nicely drawn, very imaginative, it is almost impossible to dislike. The only problem I see is the rapid shift from the playfulness of the raccoons to their grief and despair and then back again. Sometimes I didn't know if to feel sad or to laugh; sometimes I could not stop myself doing both at the same time. And that is saying much: I am city born and bred and can't stand nature much, so it was an inspiring movie.

Watch this, it is another animation gem from Studio Ghibli.

and has 0 comments
Written in 1951 by George R. Stewart, Earth Abides describes the end of civilisation by way of a deadly pandemic. The main character is an intellectual, used to observe rather than do, therefore he gains comfort in the idea of observing the end of the world. He is immune to the disease, as are few others, and so he becomes not only the observer, but the patriarch of a whole new tribe of people.

The pace of the storytelling is rather slow and the story itself spans several decades, until Ish dies of old age. The book is clearly well written, and I would say well thought, as well, but I take issue with Ish's character. He is proud of being an intellectual, of reading books, he worries all the time about the fate of civilisation, but he really does nothing to share his knowledge or do something of what he is thinking of. I know that's a trait I share, unfortunately, but his level of passivity is insane.

If at the beginning of the book I was relishing the description of the single guy finding ways to survive, both physically and mentally, then liking the way the little group of people was growing into a tribe, then I kept waiting for something else to happen. Instead, they all become complacent, living in houses they didn't know how to maintain, using products from abandoned shops they did not care to learn how to make, forgetting how to read, and so on. The biggest calling of an intellectual is to continually learn and teach. Instead, in what I see as great hypocrisy, Ish is merely content to be slightly more learned than the people around him, thinking to himself like he was reading from the Bible, even if he considered himself as an atheist rationalist, then having hopes that his child will grow to be an intellectual and spread it around, as he was doing none of that. He just complained endlessly about how stuff should be! That was infuriating.

Perhaps that is why it took so long to finish the book, as the ending felt horrifying and even insulting to me: people living like the old American indigens and caring not one bit of the immense body of knowledge that came before them. Perhaps what was worse is that this scenario seems very plausible, too.

What was refreshing (if you can use this word for a book that is 60 years old) is that there were no depictions of warrior groups roaming the land, looking for slaves or whatever, or any other type of antagonistic situations that required heroic violent response. It seems to me that this is almost a requirement in modern apocalyptic sci-fi, if not in most of it.

The style of the writing and the thoughts of its main character are a bit dated, but not terribly so. Electricity is not really useful for much other than lightning and maybe listening to radio, so they don't feel they need to maintain it one bit. Women are not as learned or smart as are the men, but that's OK, because they are women. It is normal for some people to not know how to read. A man can decide for another what is best, just because he thinks he is smarter, and it is only civilised to let them choose for themselves and completely optional. Buildings are mostly wood, so a big fire would burn a town to nothing. And so on and so on.

I can't put my finger on it, but there is something 50ish about the mindset of the lead character that definitely feels alien to me now. Perhaps the idea that, even if he were to make the effort to teach the children to read, the only books that would be of use would be technical or science. That's an incredibly weird point of view to find in a fantasy literature book.

Anyway, as one D.D.Shade lamented in a 1998 review of this book: When you're talking to someone you just met and you discover they 'love' science fiction, and you ask with great anticipation if they have read Earth Abides, the answer is "No, should I?". I agree with the man. The book should be read and should be known, as a classic of the genre and a reminder of how "the first Americans" thought about these things. Don't expect to go all "Wow!" while reading it, but as it stands, there are few books that are as thorough about the end of civilisation as this one.

I've read Legends of Earthsea and so I knew a little bit who the characters were and what the story was supposed to be. And still I got confused on what exactly had Tales from Earthsea in common with the books I remember. First of all it is a loose adaptation of the third book, so if you don't know who Sparrowhawk or Tenar are, you are out of luck. Also the Nipponification of the characters makes things a bit lame; for example Tenar is a kind and spirited woman, but completely helpless and always in need of a male to come rescue her. Even Sparrowhawk, the greatest mage in existence, is easily captured or fooled. Then there is the repetition of the same bullshit that without death there can be no life, the reason that Cob needs to be defeated. It's such a Japanese way of accepting fate that has nothing to do with the Le Guin books.

Basically Goro Miyazaki turned this beautiful fantasy into a moralizing piece of crap, where the biggest sin is that one wants to avoid death. The anime is missing the point of the books, it's completely unintelligible without reading those books, and finally does nothing for the viewer. Just read the books and enjoy the story. Or at least see the mini series ecranization of the first three books, with Shawn Ashmore as Sparrowhawk and the beautiful Kristin Kreuk as Tenar. This anime, unfortunately, had nothing working for it except the excellent animation.

Just to understand how bad this film is, I went to Imdb to rate it and I noticed that I had already rated it before. So I have seen it already, but forgotten about it. That's how unmemorable it is.

If you go to the system Internet Settings (in Network Connections, or Internet Explorer or Chrome), and you advance to the Tab "Connections", then click LAN Settings, then go to Advanced... I mean, why wouldn't you? ... there is a checkbox called "Use automatic configuration script". The script is supposed to dynamically return the correct proxy for an URL. The practice is called Proxy Auto Configuration for some reason. The script is Javascript and it uses some predefined functions to return either "DIRECT" (don't use a proxy) or "PROXY address:port" (use the proxy at that address and port). You can chain the options by separating them with a semicolon like this: "PROXY 1.2.3.4:55 ; PROXY 10.20.30.40:50; DIRECT". And before you search like a madman for it, there is no way to specify the username/password for those proxy servers in your config file. You still have to type them when asked.

Use this solution to fix problems with proxies that work well for outside sites, but not for internal networks. For reasons too weird to explain here (but explained here: Understanding Web Proxy Configuration) you cannot just put your script on the local drive and use it, instead you have to read it from an http URL. If you don't have the possibility (or it's too annoying) to install IIS or some other web server in order to serve the pac file, try using it from the local drive with a file:// URL (not just C:\...). However, it is a deprecated method and you may experience issues, with .NET software or Internet Explorer 11, for example.

Here is a sample file that connects directly to any URL that is part of a domain or is part of an IP class:
function FindProxyForURL(url, host) {

var defProxy="10.20.30.40:50"; // the misbehaving or incomplete proxy

var domains=[
".mysite.com",
".xxx",
"localhost"
];
var ipClasses=[
"11.22.33.0",
"55.0.0.0",
"127.0.0.0"
];

for (var i=0; i<domains.length; i++) {
if (dnsDomainIs(host,domains[i])) return "DIRECT";
}

var MYHOST = dnsResolve(host);

for (var i=0; i<ipClasses.length; i++) {
var mask=getMask(ipClasses[i]);
if (isInNet(MYHOST, ipClasses[i],mask)) return "DIRECT";
}

return "PROXY "+defProxy;

function getMask(ip) {
var splits=ip.split('.');
for (var i=0; i<splits.length; i++) {
if (splits[i]!='0') splits[i]='255';
}
return splits.join('.');
}

}

Just add the domains or the IP classes to the arrays in order to connect directly to them. Do not forget to add the local IP classes as well for direct connection, including 127.0.0.0 to access your own localhost.

In order to test or debug your .pac files, use the PacParser open source utility. A reference to the functions you can use in your script can be found here: Using Automatic Configuration, Automatic Proxy, and Automatic Detection

MinMax or Minimax, as some like to call it, is the basis of most Artificial Intelligence built for games like chess. Its basis is extremely easy to understand: a rational player will try to take the best option available to them, so whatever is good for me the adversary will take as the most likely outcome and he will find the best solution against that outcome. I, following the same pattern, will also look for his best counter move and plan against it. Therefore the thinking for a game of chess, let's say, is that I will take all possible moves, find the one that leaves me with the best position (evaluated by a function from the board position), then look for the similar best play for the adversary. I continue this way until I get to the end of the game or am out of computing resources.

Now, that sounds logical and it's crazy easy to implement. The problem is that for all but the most childish of plays, the tree of all possible moves increases exponentially. And chess isn't even one of the worst games to do that. Imagine Tic-Tac-Toe, a game played on a 3x3 board between two players. You have a total of 9 possible moves to choose from as the first player, then 8, then 7, etc. The entire game tree has a total of 9! possible moves, or 362880. But generalize the game to a board of 10x10 and a winning rule of 5 in a line and you get 100! moves, which is less than 1E+158, that is 10 followed by 158 zeros.

That's why the so called pruning was created, the most common of all being Alpha-Beta, which tries to abort the processing of leaves that seem to reach a worse situation than their parent node. Of course, all of this is the general gist. You might want to take into account a number N best moves from the opponent, as well as try a more lenient pruning algorithm (after all, sacrificing a piece brings you to a worse position than when you started, but it might win the game). All of this increases, not decreases the number of possible moves.

And now comes my thought on this whole thing: how can I make a computer play like a human when the core edict of the algorithm is that all participating players are rational? Humans are rarely so. Mathematically I could take N, the number of best moves I would consider for my opponent, to be the total number of moves my opponent could make, but it would increase the exponential base of the tree of moves. Basically it would make the algorithm think of stupid things all the time.

The pruning algorithm seems to be the most important part of the equation. Indeed, I could consider the move choice algorithm to be completely random and as long as I have a perfect pruning algorithm it will remove all the stupid choices from me and let me with the smart ones. A quote comes to mind: "you reach perfection not when you have nothing else to add, but when there is nothing left to remove". It's appropriate for this situation.

Now, before attacking an algorithm that has survived for so long in the AI industry (and making my own awesome one that will defeat all chess engines in the world - of course, that's realistic) I have to consider the alternative algorithm: the lowly human. How does a human player think in a game of chess? First he surveys the board for any easy wins. That means a broad one or two levels analysis based on a simple board evaluation function. Immediately we get something from this: there might be multiple evaluation functions, we don't need just one. The simple one is for looking for greedy wins, like "He moved his queen where I can capture it, yay!".

The same outcome for situations like this would be achieved by a MinMax algorithm, so we ignore this situation. It gets more interesting from now, though. We look for the moves of the most active pieces. I know that this is the rookie system, but I am a rookie, I will make my computer algorithm be as stupid as I am, if I am to play it, so shut up! The rookie will always try to move his queen to attack something. It's the most powerful piece and it should get the most results for the least effort. We left Greed behind, remember? We are now doing Sloth. Still, with a good pruning algorithm we eliminate stupid Queen moves from the beginning, so considering the Queen first, then Rooks, then Bishops, then Knights, etc. is not a bad idea. The order of the pieces can be changed based on personal preferences as well as well established chess rules, like Knights being better that Bishops in closed games and so on.

This is a small optimization, one that probably most game engines have. And we haven't even touched pruning; boy, this is going to be a long article! Now, what does the human do? He does the depth first tree searches. Well, he doesn't think of them like that, he thinks of them as narrative, but it's basically a depth first search. This is the casual "What if...?" type of play. You move the Queen, let's say, bringing it right in the enemy territory. You don't capture anything important, but to bring a strong piece this uncomfortably near to the enemy king is scary. You don't play for game points, but for emotion points, for special effects, for kicks! You don't abandon the narrative, the linear evolution of your attack, until you find that it bears no fruit. It's the equivalent of the hero running toward the enemy firing his pistol. If the enemy is dumb enough to not take cover, aim carefully and shoot a burst from their SMGs, you might get away with it and it would be glorious. If not, you die idiotically.

It is important to note that in the "Hollywood" chess thinking you are prone to assume that the enemy will make mistakes in order to facilitate your brilliant plan. The evaluation goes as follows: "I will try something that looks cool if the chances for a horrible and immediate loss are small". When some hurdle foils your heroic plan, you make subplans that would, as well as you hope, distract the adversary from your actual target. This, as far as I know, is a typical human reasoning type and I doubt many (if any) computer game engines have it. In computer terms, one would have to define a completely new game, a smaller one, and direct an AI designed specifically for it to tell you if it would work or not. Given the massively parallel architecture of the human brain, it is not hard to understand why we do something like this. But we can do the same with a computer, mind you. I am thinking of something like a customized MinMax algorithm working on few levels, one or two, as the human would. That would result in a choice of N possible moves to make. Then construct a narrative for each, a depth search that just tries to get as much as possible from each move without considering many of the implications. Then assign a risk to each level of this story. If the level exceeds a threshold, use the small range MinMax at those points and try to see if you can minimize the risk or if at that point the risk makes your narrative unlikely.


Let's recap the human thinking algorithm so far:
  1. Try to greedily take what the opponent has stupidly made available
  2. Try to lazily use the strongest piece to get the most result with the least effort
  3. Try to pridefully find the most showy move, the one that would make the best drinking story afterwards
  4. Try to delegate the solving of individual problems in your heroic narrative to a different routine

Wow! Doesn't it seem that the seven deadly sins are built-in features, rather than bugs? How come we enjoy playing with opponents that pretty much go through each of them in order to win more than we do with a rational emotionless algorithm that only does what is right?

Again, something relevant transpires: we take quite a long time imagining the best moves we can make, but we think less of the opponent's replies. In computer terms we would prune a lot more the enemy possible moves than we would our own. In most rookie cases, one gets absorbed by their own attack and ignores moves that could counterattack. It's not intuitive to think that while you are punching somebody, they would choose to punch back rather than avoid the pain. In chess it's a little bit easier and more effective, since you can abandon a piece in order to achieve an overall gain in the game, but it can and it is done in physical combat as well.

Okay, we now have two alternatives. One is the logical one: take into account all the rules chess masters have taught us, shortcuts for achieving a better position on the board; choose moves based on those principles and then gauge the likely response from the opponent. Repeat. This is exactly like a MinMax algorithm! So we won't do that. The hell with it! If I can't enjoy the game, neither will my enemy!!

Human solution: don't do anything. Think of what your opponent would do, if you wouldn't move anything and foil their immediate plan. This way of thinking would be counterintuitive for a computer algorithm. Functioning on the basis of specific game rules, a computer would never be inclined to think "what would the enemy do if I didn't move anything, which is ILLEGAL in chess?". That makes us superior, obviously ;-)

Slowly, but surely, a third component of the algorithm becomes apparent: the move order choice. Let's imagine a naive MinMax implementation. In order to assess every possible move, it would have to enumerate them. If the list of moves is always the same in a certain board position, the game will always proceed the same way. The solution is to take the list of possible moves, but in a random order. In the case of the "human algorithm" the ordering becomes more complex (favouring powerful piece moves, for example). One could even consider the ordering mechanism responsible for choosing whether to do a careful breadth search for each level or a depth first one.


Here is a suggestion for an algorithm, one that takes into account the story of the game and less the objective gain or position strength:
  1. For each of your power pieces - anything but the king and pawns - compute mobility, or the possibility to move and attack. Favour the stronger pieces first.
  2. For each power piece with low mobility consider pawn moves that would maximize that mobility.
  3. For each power piece with high mobility consider the moves that would increase the chance of attack or that would attack directly
  4. For each strong move, consider the obstacles - enemy pieces, own pieces, possible enemy countermeasures
  5. Make the move that enables the considered power move or that foils the enemy attempts of reply

The advantage of this approach is that it only takes into account the enemy when he can do something to stop you, the pawns only when they can enable your devious plan and focuses on ventures that yield the best attack for your heroes. For any obstruction, you delegate the resolution of the problem to a different routine. This makes the algorithm parallelizable as well as modular - something we devs love because we can test the individual parts separately.

This algorithm would still use a board estimation function, but being more focused on heroic attacks, it would prefer interesting move orders to static positions as well as the "fun factor", something that is essential to a human-like algorithm. If the end result of the attack is a check-mate, then it doesn't really matter what position estimate you get when you did half the moves. All one has to wonder is if the attack is going to be successful or not and if one can do something to improve the chances of success. And indeed this is one of the most difficult aspects for a chess playing human: to switch from a failing plan to a successful plan when it is not yet clear is the first plan is failing. We invest energy and thought into an idea and we want it to work. A lot of the chess playing strategy of human rookies relies on prayer, after all. A computer would just assess the situation anew at every move, even if it has a strategy cached somewhere. If the situation demands it, a new strategy will be created and the last one abandoned. It's like killing your child and making another!


But, you will say, all you did so far was to describe an inferior algorithm that can be approximated by MinMax with only custom choices for the pruning and move order functions! You are missing the point. What I am describing is not supposed to beat Grand Masters, but to play a fun game with you, the casual player. More than that, my point is that for different desired results, different algorithms must be employed. This would be akin to creating a different AI for each level of a chess game.

Then there is the issue of the generalized TicTacToe or other games, such as Arimaa, created specially to make it difficult for computer algorithms to play, where MinMax fails completely. To make a comparison to real life, it's like you would consider the career steps you would take in life based on all possible jobs available, imagining what would it be to be employed there, what the difficulties might be, finding solutions to those problems, repeating the procedure. You will get to the conclusion that it is a good idea to become a computer scientist after thoroughly examining and partially understanding what it would be like to be a garbage man, a quantum scientist, a politician and a gigolo, as well as all the jobs in between. Of course, that is not as far fetched as you think, since in order to be a success in software development you must be at least a politician and a garbage man, perhaps even a gigolo. Lucky for our profession, quantum computers are in the works, too.

The same incongruency can be found when thinking of other games humans enjoy, like races. The desired result can only be achieved at the end of the race, when you actually get somewhere. In order to get to that specific point in space, you could consider the individual value of each direction change, or even of each step. However humans do it differently, they specify waypoints that must be achieved in order to get to the finish and then focus on getting from waypoint to waypoint, rather than rethinking the entire course. In computer terms this is a divide-and-conquer strategem, where one tries to solve a problem that has known start and end points by introducing a middle point and then solving the problem from the start to the middle. BTW, this also solves Zeno's paradox: "Why does the arrow reach its target if, at any point in its course, it has at least half the distance left to fly?" and the answer is "Because of the exit condition that prevents a stack overflow". Try to sell that one in a philosophy class, heh heh.


So why aren't chess AIs based on human thinking processes? Why don't they implement a divide and conquer solution for a game that always starts with a specific board position and ends in capturing a specific piece? Why do chess engines lower their "level" by sometimes randomly choosing a completely losing path instead of something that is plausible to choose, even if completely wrong objectively? How can MinMax be the best general algorithm for game AIs, when some of them have a branching factor that makes the use of the algorithm almost useless?

I obviously don't have the answers to these questions, but I may have an opportunity to explore them. Hopefully I will be less lazy than I usually am and invent something completely unscientific, but totally fun! Wish me luck!