5 // FOR COMMUNICATION //////////////////////////////////////////
12 void OnSerialize(SerialBuffer buffer)
16 buffer.Serialize(letter);
17 buffer.Serialize(blankValue);
20 void OnUnserialize(SerialBuffer buffer)
22 buffer.Unserialize(x);
23 buffer.Unserialize(y);
24 buffer.Unserialize(letter);
25 buffer.Unserialize(blankValue);
36 void OnSerialize(SerialBuffer buffer)
39 buffer.Serialize(numTiles);
41 buffer.Serialize(tiles[c]);
42 buffer.Serialize(player);
43 buffer.Serialize(score);
46 void OnUnserialize(SerialBuffer buffer)
49 buffer.Unserialize(numTiles);
51 buffer.Unserialize(tiles[c]);
52 buffer.Unserialize(player);
53 buffer.Unserialize(score);
62 void OnSerialize(SerialBuffer buffer)
64 buffer.Serialize(language);
65 buffer.Serialize((StaticString)players[0]);
66 buffer.Serialize((StaticString)players[1]);
67 buffer.Serialize((StaticString)players[2]);
68 buffer.Serialize((StaticString)players[3]);
71 void OnUnserialize(SerialBuffer buffer)
73 buffer.Unserialize(language);
74 buffer.Unserialize((StaticString)players[0]);
75 buffer.Unserialize((StaticString)players[1]);
76 buffer.Unserialize((StaticString)players[2]);
77 buffer.Unserialize((StaticString)players[3]);
81 //////////////////////////////////////////
91 ServerConnection connection;
99 static const char * dicos[Languages] = { ":englishWords.txt", ":frenchWords.txt" };
103 int lettersAvailable[Letters];
104 int numLettersAvailable;
105 AVLTree<String> dictionary { };
107 Player players[MaxPlayers];
110 property Languages language
115 LoadWords(dicos[value]);
119 Letters board[15][15];
120 Letters blankValues[15][15];
128 for(c = 0; c<MaxPlayers; c++)
137 void GetTiles(int tilesPlayer, PlayedMove move)
139 Player player = players[tilesPlayer];
142 while(player.numLetters < 7 && numLettersAvailable)
145 int r = (Letters)GetRandom(0, numLettersAvailable-1);
148 for(letter = 0; letter<Letters::empty; letter++)
150 a += lettersAvailable[letter];
154 numLettersAvailable--;
155 lettersAvailable[letter]--;
157 player.letters[player.numLetters] = letter;
160 move.tiles[move.numTiles++].letter = letter;
169 for(c = 0; c<MaxPlayers; c++)
178 PlayedMove tiles { };
180 numLettersAvailable = 0;
182 for(l = 0; l<Letters::empty; l++)
184 numLettersAvailable += lettersCount[language][l];
185 lettersAvailable[l] = lettersCount[language][l];
188 seed = (uint)(((uint64)(GetTime() * 1000)) & MAXDWORD);
191 //Logf("Seeded with %d\n", seed);
193 for(y = 0; y<15; y++)
194 for(x = 0; x<15; x++)
195 board[y][x] = blankValues[y][x] = empty;
198 for(c = 0; c<MaxPlayers; c++)
207 strcpy(list.players[0], crossWordsGame.players[0] ? crossWordsGame.players[0].name : "");
208 strcpy(list.players[1], crossWordsGame.players[1] ? crossWordsGame.players[1].name : "");
209 strcpy(list.players[2], crossWordsGame.players[2] ? crossWordsGame.players[2].name : "");
210 strcpy(list.players[3], crossWordsGame.players[3] ? crossWordsGame.players[3].name : "");
211 list.language = crossWordsGame.language;
213 for(c = 0; c<MaxPlayers; c++)
216 crossWordsGame.GetTiles(c, tiles);
217 crossWordsGame.players[c].connection.GameStarted(list, tiles);
222 void LoadWords(const char * fileName)
224 File f = FileOpen(fileName, read);
231 f.GetLine(word, sizeof(word));
234 String s = CopyString(word);
235 if(!dictionary.Add(s))
243 IteratorPointer test1, test2;
244 test1 = dictionary.Find("gewurztraminer");
245 test2 = dictionary.Find("gewurstraminer");
250 bool CheckWord(Letters newBoard[15][15], Direction direction, int where, int start, int end, int * score)
256 int wordMultiplier = 1;
258 for(c = start; c<= end; c++)
260 int y = direction ? c : where;
261 int x = direction ? where : c;
262 Letters letter = newBoard[y][x];
265 if(board[y][x] == empty)
267 if(squareValues[y][x] == doubleLetter) multiplier = 2;
268 else if(squareValues[y][x] == tripleLetter) multiplier = 3;
271 wordScore += lettersValue[language][letter] * multiplier;
273 if(board[y][x] == empty)
275 if(squareValues[y][x] == doubleWord) wordMultiplier *= 2;
276 else if(squareValues[y][x] == tripleWord) wordMultiplier *= 3;
280 letter = blankValues[y][x];
281 word[len++] = (char)(letter + 'a');
284 found = dictionary.Find(word) != null;
285 Logf("%s: %s\n", word, found ? "found :)" : "not found :(");
287 *score += wordScore * wordMultiplier;
291 bool VerifyMove(Letters newBoard[15][15], int * score)
296 Direction direction = horizontal;
300 int firstX = MAXINT, lastX = MININT;
301 int firstY = MAXINT, lastY = MININT;
302 int first, last, where;
303 int wordStart, wordEnd;
304 bool anchored = false;
308 for(y = 0; y<15; y++)
310 for(x = 0; x<15; x++)
312 if(board[y][x] == empty && newBoard[y][x] != empty)
316 if(x < firstX) firstX = x;
317 if(y < firstY) firstY = y;
318 if(x > lastX) lastX = x;
319 if(y > lastY) lastY = y;
324 if(!numLetters) return false;
325 if(lastY - firstY > 0)
327 if(lastX - firstX > 1) return false;
328 direction = vertical;
330 else if(lastX - firstX == 0)
332 if(((firstY > 0 && newBoard[firstY-1][firstX] != empty) ||
333 (firstY < 14 && newBoard[firstY+1][firstX] != empty)) &&
334 ((firstX == 0 || newBoard[firstY][firstX-1] == empty) &&
335 (firstX == 14 || newBoard[firstY][firstX+1] == empty)))
336 direction = vertical;
339 first = direction ? firstY : firstX;
340 last = direction ? lastY : lastX;
342 where = direction ? firstX : firstY;
344 for(c = first; c <= last; c++)
346 Letters letter = direction ? newBoard[c][where] : newBoard[where][c];
347 if(letter == empty) return false;
350 for(c = first; c>=0; c--)
352 Letters letter = direction ? newBoard[c][where] : newBoard[where][c];
353 if(letter == empty) break;
358 for(c = last; c<15; c++)
360 Letters letter = direction ? newBoard[c][where] : newBoard[where][c];
361 if(letter == empty) break;
366 if(!CheckWord(newBoard, direction, where, wordStart, wordEnd, score))
369 for(c = first; c <= last; c++)
371 if((direction ? board[c][where] : board[where][c]) == empty)
373 int wordStart, wordEnd;
376 for(a = where; a>=0; a--)
378 Letters letter = direction ? newBoard[c][a] : newBoard[a][c];
379 if(letter == empty) break;
384 for(a = where; a<15; a++)
386 Letters letter = direction ? newBoard[c][a] : newBoard[a][c];
387 if(letter == empty) break;
392 if(wordEnd > wordStart)
393 if(!CheckWord(newBoard, direction^1, c, wordStart, wordEnd, score))
399 if(newBoard[7][7] != empty && board[7][7] == empty) anchored = true;
400 if(!anchored) return false;
401 if(numLetters == 7) *score += 50;
410 for(c = 0; c<MaxPlayers; c++)
412 delete crossWordsGame.players[c];
419 CrossWordsGame crossWordsGame;
421 remote class ServerConnection
431 //crossWordsGame.players[player.id] = null;
432 delete crossWordsGame.players[player.id];
434 crossWordsGame.EndGame();
441 if(!crossWordsGame.gameStarted)
444 for(c = 0; c<MaxPlayers; c++)
446 if(!crossWordsGame.players[c])
451 player = crossWordsGame.players[c] = Player { id = c };
452 player.connection = this;
454 incref crossWordsGame.players[c];
461 bool SetName(const String name)
465 player.name = CopyString(name);
466 if(!crossWords.scoreFields[player.id])
468 crossWords.scoreFields[player.id] = DataField { dataType = class(int), header = name, width = 40 };
469 //incref crossWords.scoreFields[player.id];
470 crossWords.scores.AddField(crossWords.scoreFields[player.id]);
472 crossWords.scoreFields[player.id].header = name;
477 bool PlayTiles(PlayedMove move)
479 if(player && crossWordsGame.players[crossWordsGame.curPlayer] == player)
481 Letters newBoard[15][15];
485 memcpy(newBoard, crossWordsGame.board, 15*15*sizeof(Letters));
486 for(c = 0; c<move.numTiles; c++)
488 if(newBoard[move.tiles[c].y][move.tiles[c].x] == empty)
490 newBoard[move.tiles[c].y][move.tiles[c].x] = move.tiles[c].letter;
491 crossWordsGame.blankValues[move.tiles[c].y][move.tiles[c].x] = move.tiles[c].blankValue;
496 if(crossWordsGame.VerifyMove(newBoard, &score))
498 for(c = 0; c<move.numTiles; c++)
502 for(d = 0; d<player.numLetters; d++)
503 if(player.letters[d] == move.tiles[c].letter)
505 memmove(player.letters + d, player.letters + d + 1, sizeof(int) * (player.numLetters - d - 1));
512 Logf("Letter not found!\n");
517 player.totalScore += score;
518 memcpy(crossWordsGame.board, newBoard, 15*15*sizeof(Letters));
520 crossWordsGame.curMove = move;
521 crossWordsGame.curMove.player = crossWordsGame.curPlayer;
522 crossWordsGame.curMove.score = score;
525 crossWordsGame.GetTiles(crossWordsGame.curPlayer, move);
527 for(c = 0; c<MaxPlayers; c++)
528 if(crossWordsGame.players[c])
529 crossWordsGame.players[c].connection.MovePlayed(crossWordsGame.curMove);
531 do { if(++crossWordsGame.curPlayer == MaxPlayers) crossWordsGame.curPlayer = 0; } while(!crossWordsGame.players[crossWordsGame.curPlayer]);
538 bool DiscardTiles(PlayedMove move)
540 if(player && crossWordsGame.numLettersAvailable >= move.numTiles && crossWordsGame.players[crossWordsGame.curPlayer] == player)
543 PlayedMove newTiles { };
545 for(c = 0; c<move.numTiles; c++)
548 for(d = 0; d<player.numLetters; d++)
549 if(player.letters[d] == move.tiles[c].letter)
551 memmove(player.letters + d, player.letters + d + 1, sizeof(int) * (player.numLetters - d - 1));
557 crossWordsGame.GetTiles(crossWordsGame.curPlayer, newTiles);
559 for(c = 0; c<move.numTiles; c++)
561 crossWordsGame.lettersAvailable[move.tiles[c].letter]++;
562 crossWordsGame.numLettersAvailable++;
565 crossWordsGame.curMove = { }; // TODO: Add informing other players of number of exchanged letters when passing...
566 crossWordsGame.curMove.player = crossWordsGame.curPlayer;
570 for(c = 0; c<MaxPlayers; c++)
571 if(crossWordsGame.players[c])
572 crossWordsGame.players[c].connection.MovePlayed(crossWordsGame.curMove);
574 do { if(++crossWordsGame.curPlayer == MaxPlayers) crossWordsGame.curPlayer = 0; } while(!crossWordsGame.players[crossWordsGame.curPlayer]);
581 virtual void MovePlayed(PlayedMove move);
582 virtual void GameStarted(PlayerList list, PlayedMove tiles);