Soi is a four player card game of memory and logic. While memory alone should be enough to guide a player through the game, logic helps in many cases. It is very easy to learn, but not so easy to play. The object of the game is to collect as many points as you can, by collecting all four suits of whatever cards you have on each round. For example, if you have 4 of hearts, your object is to collect the other three suits for that number. Namely, 4 of spades, 4 of clubs and 4 of diamonds. To do that, you simply ask any of the players to give you the specific card you want. For example, you can ask the player opposite to you for the card 4 of diamonds. If the player you ask has the card, they are obliged to give it to you, and you can continue asking for another card the same player or any other player in exactly the same manner. If however the player you've asked for a card does not in fact own it, your turn is forfeited and that player (the one you have asked the card from) assumes the right to continue, using exactly the same technique. Namely, they can go on asking for any card they wish, until they are unsuccessful. Once all four suits of a particular kind are collected, the quadruplet is deposited on the playing table, and does not participate in the game any more.
The game consists of rounds with each player starting with 13 arbitrary cards. The cards are dealt on the table, and an arbitrary player goes first, based on some external criterion, say the one that draws the largest face value from the deck. Here, the computer decides who will go first using a random number generator. A round is active for as long as there are any cards pending, in the hands of players. The round ends when all cards have been deposited. Representatives of the deposited cards are always shown next to the free cards. At the end of a round, any collected quadruplet of four suits, is worth precisely the face value of the card-kind it represents. For example, all four suits of 5 are worth 5 points, etc., except all four Aces, which are worth 25 points. Jacks, Queens and Kings, are worth 10 points. At the end of each round, the cards are counted, and each player's total score is added to a cumulative total for each player. Then, the deck is re-shuffled, dealt again and another round begins. Within any round, you must have at least one card of any suit, to have the right to ask for the other suits of that kind. If you have for example no cards of the 5 kind, you cannot ask for fives. You can be thrown out from a round, if you run out of cards, i.e. if the other players get your cards. If you collect all the suits for your particular kinds and deposit them, i.e. when you finish playing with your cards, the player next to you counterclockwise continues. The game ends when some global point value is reached, at the end of some round. This point value, can be variable. You can set it at 200 points, or 500 points. Accordingly then, when the game ends, there will be an winner and three losers, who are numbered according to their total score. The winner will be announced at the end of the game.
The game can be hard to beat, particularly on the "impossible" level.
Soi needs a color Macintosh. It also needs at least System version 7.0.0.
Soi's most difficult part was its move generator engine. The engine related units present one particular implementation of a move generator. The move generator uses a semi-static priority table ([OneCard..ThreeCards]x[Ace,Two,...,King]) which stores move priorities. The analysis is semi-static, meaning that a static analysis is performed, but a dynamic component is also calculated, based on the particular memory arrays for each player. The moves are prioritized, based on the past moves of other players and current states (dynamic component) and evaluations based on current card configurations (static component).
In the beginning of the game, when there is no memory data, the analysis is mostly static. As soon as data starts seeping in, the analysis takes on the dynamic component as well. Because the analysis needs to take on a dynamic component and the next move depends on any prior moves made, the table is recalculated for every move, except for the certain cases or what the analysis considers certain anyway, where a sequential move is generated that consists of more than one moves.
Even though primitive, the algorithm reaches its goal easily, thing which can be shown by letting the machine play by itself.
On a more theoretical level, the assigned priorities for all the card moves impose an ordering on all the card hands. A card hand may be represented by a string , "2s2c2h3h3d6s6djhjd..." etc, say, where the goal of the game is to reduce the string to a null string ("") by applying the rule "...xsxcxhxd..." -> "...", where x is any kind; in other words, all four suits are equivalent to null. It's interesting to try to formulate the rules of the game using a particular deduction system that has as objects the dealt hands (strings) and as rule the above rule.
Download Soi here. If you prefer the Greek localized version, download it here.
Back to Programming