Click here to Skip to main content
15,895,746 members
Articles / Web Development / ASP.NET

Online Circular Chess in Silverlight, ASP.NET AJAX, WCF Web Services, and LINQ to SQL

Rate me:
Please Sign up or sign in to vote.
4.84/5 (61 votes)
31 Dec 2007CPOL34 min read 220.5K   1.9K   145  
An application for users to play Circular Chess over the internet based on Silverlight, ASP.NET AJAX, WCF Web Services, and LINQ to SQL.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Activation;
using System.Web;

namespace CChess
{
    [DataContract(Name = "CChessGameColors", Namespace = "")]
    public enum CChessGameColors : byte
    {
        [EnumMember()]
        White = 1,
        [EnumMember()]
        Black
    }

    [DataContract(Name = "CChessGameStates", Namespace = "")]
    public enum CChessGameStates : byte
    {
        [EnumMember()]
        NotStarted = 1,
        [EnumMember()]
        OnGoing,
        [EnumMember()]
        Finished
    }

    [AspNetCompatibilityRequirements(
        RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class CChessService : ICChessService
    {

        #region Authentication Region

        public void Login(CChessPlayer new_player)
        {
            CChessDataContext cdc = new CChessDataContext();

            new_player.last_activity = UnixDate.GetCurrentUnixTimestamp();
            //CChessPlayer new_player = new CChessPlayer() { player_nick = nickname, last_activity = UnixDate.GetCurrentUnixTimestamp() };
            cdc.CChessPlayers.InsertOnSubmit(new_player);
            cdc.SubmitChanges();
            // Store the player in his profile
            ProfileCommon profile = (ProfileCommon)HttpContext.Current.Profile;
            profile.CChessPlayer = new_player;
        }

        public void UpdateUserActivity()
        {
            CChessPlayer player = ((ProfileCommon)HttpContext.Current.Profile).CChessPlayer;
            if (player == null)
            {
                throw new Exception("You're not online.");
            }

            CChessDataContext cdc = new CChessDataContext();

            // Now, the reason I've used a stored procedure instead of standard Linq
            // is because in order to get player to be traced by the DataContext,
            // I'd need to select it again, and then update it. In this case, a 
            // standard stored procedure is a far better option (I'd even say
            // an easier solution).
            int affected_rows = cdc.UpdateUserActivity(player.player_id, UnixDate.GetCurrentUnixTimestamp());
            if (affected_rows < 1)
            {
                throw new Exception("Unable to update activity.");
            }
        }

        public List<CChessPlayer> GetOnlineUsers()
        {
            CChessDataContext cdc = new CChessDataContext();

            return cdc.GetOnlinePlayers(CChessPlayer.LEGAL_INACTIVITY_SECONDS, UnixDate.GetCurrentUnixTimestamp()).ToList<CChessPlayer>();
        }

        #endregion

        #region Chat Region

        public List<ChatMessage> GetLastNMessages(int n)
        {
            CChessDataContext cdc = new CChessDataContext();
            List<ChatMessage> messages = (from msgs in cdc.ChatMessages
                              orderby msgs.message_id descending
                              select msgs).Take(n).ToList();

            return messages;
        }

        public void SendMessage(String content)
        {
            CChessPlayer current_player = ((ProfileCommon)HttpContext.Current.Profile).CChessPlayer;
            if (current_player == null)
            {
                return;
            }

            ChatMessage msg = new ChatMessage
            {
                message_writer = current_player.player_id,
                message_content = content,
                sent_timestamp = UnixDate.GetCurrentUnixTimestamp()
            };
            CChessDataContext cdc = new CChessDataContext();
            cdc.ChatMessages.InsertOnSubmit(msg);
            cdc.SubmitChanges();
        }

        public List<ChatMessage> GetNewMessages(int last_msg_id)
        {
            CChessDataContext cdc = new CChessDataContext();

            var messages = (from msgs in cdc.ChatMessages
                            where msgs.message_id > last_msg_id
                            select msgs);

            return messages.ToList<ChatMessage>();
        }

        #endregion

        #region Circular Chess Region

        public void CreateNewGame(CChessGameColors starting_color)
        {
            CChessDataContext cdc = new CChessDataContext();
            CChessGame new_game = new CChessGame() { game_state = (byte)CChessGameStates.NotStarted };
            
            CChessPlayer current_player = ((ProfileCommon)HttpContext.Current.Profile).CChessPlayer;
            CChessGamesPlayers new_game_player = new CChessGamesPlayers() 
            { 
                game_id = new_game.game_id, 
                player_id = current_player.player_id, 
                color = (byte)starting_color
            };

            new_game.CChessGamesPlayers.Add(new_game_player);

            cdc.CChessGames.InsertOnSubmit(new_game);
            cdc.SubmitChanges();

            ProfileCommon profile = (ProfileCommon)HttpContext.Current.Profile;
            profile.CChessGameID = new_game.game_id;
        }

        public List<CChessGamesPlayers> GetCurrentGamePlayers()
        {
            CChessDataContext cdc = new CChessDataContext();

            List<CChessGamesPlayers> current_game_players = (from games_players in cdc.CChessGamesPlayers
                                                             where UnixDate.GetCurrentUnixTimestamp() - games_players.CChessPlayer.last_activity < CChessPlayer.LEGAL_INACTIVITY_SECONDS
                                                             orderby games_players.game_id
                                                             select games_players).ToList();

            return current_game_players;
        }

        public void AddToGame(long game_id, CChessGameColors color)
        {
            CChessDataContext cdc = new CChessDataContext();

            CChessGamesPlayers new_player = new CChessGamesPlayers()
            {
                game_id = game_id,
                player_id = ((ProfileCommon)HttpContext.Current.Profile).CChessPlayer.player_id,
                color = (byte)color
            };

            cdc.CChessGamesPlayers.InsertOnSubmit(new_player);
            cdc.SubmitChanges();

            ProfileCommon profile = (ProfileCommon)HttpContext.Current.Profile;
            profile.CChessGameID = game_id;
        }

        public CChessGamesPlayers GetYou()
        {
            CChessDataContext cdc = new CChessDataContext();
            ProfileCommon profile = (ProfileCommon)HttpContext.Current.Profile;
            CChessGamesPlayers you = cdc.CChessGamesPlayers.Single(p => p.player_id == profile.CChessPlayer.player_id && p.game_id == profile.CChessGameID);
            return you;
        }

        public CChessGamesPlayers GetOpponent()
        {
            CChessDataContext cdc = new CChessDataContext();
            ProfileCommon profile = (ProfileCommon)HttpContext.Current.Profile;
            CChessGamesPlayers players = cdc.CChessGamesPlayers.FirstOrDefault(p =>
                (p.player_id != profile.CChessPlayer.player_id) &&
                (p.game_id == profile.CChessGameID) &&
                (UnixDate.GetCurrentUnixTimestamp() - p.CChessPlayer.last_activity < CChessPlayer.LEGAL_INACTIVITY_SECONDS));
            return players;
        }

        /// <summary>
        /// Submits a move to the database after checking it's valid
        /// </summary>
        /// <returns>The id of the move (mostly because I get an error in Silverlight if I return null)</returns>
        public long MovePiece(CChessMove move)
        {
            ProfileCommon profile = (ProfileCommon)HttpContext.Current.Profile;
            CChessDataContext cdc = new CChessDataContext();

            if (move.player_id == profile.CChessPlayer.player_id &&
                cdc.CChessGamesPlayers.Contains(new CChessGamesPlayers()
                {
                    player_id = move.player_id,
                    game_id = move.game_id
                }))
            {
                CChessBoard board = new CChessBoard();
                List<CChessMove> moves = GetAllMoves(move.game_id);
                foreach (CChessMove curr_move in moves)
                {
                    board.MovePiece(curr_move.piece_id, curr_move.destination_ring, curr_move.destination_square);
                }
                board.MovePiece(move.piece_id, move.destination_ring, move.destination_square);

                cdc.CChessMoves.InsertOnSubmit(move);
                cdc.SubmitChanges();

                return move.move_id;
            }
            else
            {
                throw new Exception("You're not allowed to move in this game.");
            }
        }

        public CChessMove GetLastMove(long last_move_id)
        {
            CChessDataContext cdc = new CChessDataContext();
            ProfileCommon profile = (ProfileCommon)HttpContext.Current.Profile;

            // Get the last move of the current game, where the id is greater 
            // than the last move gotten
            CChessMove last_move = cdc.CChessMoves.Where(m => m.game_id == profile.CChessGameID && m.move_id > last_move_id).OrderByDescending(m => m.move_id).FirstOrDefault();

            return last_move;
        }

        public List<CChessMove> GetAllMoves(long game_id)
        {
            CChessDataContext cdc = new CChessDataContext();

            List<CChessMove> game_moves = (from m in cdc.CChessMoves
                                           where m.game_id == game_id
                                           orderby m.move_id ascending
                                           select m).ToList();

            return game_moves;
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Israel Israel
My name is Julian, I was born in Argentina, but I've been living in Israel for 6 years already. I'm a high school student in my last year, I study computer science, physics and math.
Other than programming, I really enjoy watching anime and reading manga.

Comments and Discussions