summaryrefslogtreecommitdiff
path: root/csol.c
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2018-12-21 11:27:26 +0000
committerIan C <ianc@noddybox.co.uk>2018-12-21 11:27:26 +0000
commit1169992d50ce930143efe2851d02e7dfa0304e29 (patch)
treeb7c302c559b65a05f0b552244e57b2a4aed6cff2 /csol.c
parent859dc1c2044140f7bae42705940e44b4c94bd07e (diff)
Split code up into separate objects.
Diffstat (limited to 'csol.c')
-rw-r--r--csol.c833
1 files changed, 4 insertions, 829 deletions
diff --git a/csol.c b/csol.c
index f07e755..1abfcc9 100644
--- a/csol.c
+++ b/csol.c
@@ -23,840 +23,15 @@
*/
#include <stdlib.h>
-#include <limits.h>
#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
#include <time.h>
#include <curses.h>
-typedef enum
-{
- NoSuit = 0,
- Heart = 'H',
- Diamond = 'D',
- Club = 'C',
- Spade = 'S'
-} Suit;
-
-typedef struct
-{
- int value;
- Suit suit;
-} Card;
-
-typedef Card Deck[52];
-
-typedef struct
-{
- int no;
- Card *card;
-} Pile;
-
-static void Fatal(const char *p)
-{
- endwin();
- fprintf(stderr, "%s\n", p);
- exit(EXIT_FAILURE);
-}
-
-static void Init(Deck deck)
-{
- int i = 0;
- int f;
-
- for(f=1; f < 14; f++)
- {
- deck[i].suit = Heart;
- deck[i++].value = f;
-
- deck[i].suit = Diamond;
- deck[i++].value = f;
-
- deck[i].suit = Club;
- deck[i++].value = f;
-
- deck[i].suit = Spade;
- deck[i++].value = f;
- }
-}
-
-static void Shuffle(Deck deck)
-{
- int f;
-
- for(f = 0; f < 1000; f++)
- {
- int c1 = rand() % 52;
- int c2 = rand() % 52;
- Card c;
-
- c = deck[c1];
- deck[c1] = deck[c2];
- deck[c2] = c;
- }
-}
-
-static void AddToPile(Pile *pile, Card card)
-{
- pile->no++;
-
- pile->card = realloc(pile->card, sizeof *pile->card * pile->no);
-
- if (!pile->card)
- {
- Fatal("Failed to reallocate memory");
- }
- else
- {
- pile->card[pile->no - 1] = card;
- }
-}
-
-static void InsertBottomOfPile(Pile *pile, Card card)
-{
- pile->no++;
-
- pile->card = realloc(pile->card, sizeof *pile->card * pile->no);
-
- if (!pile->card)
- {
- Fatal("Failed to reallocate memory");
- }
- else
- {
- int f;
-
- for(f = pile->no - 1; f > 0; f--)
- {
- pile->card[f] = pile->card[f - 1];
- }
-
- pile->card[0] = card;
- }
-}
-
-static Card PopPile(Pile *pile)
-{
- Card c = {0};
-
- if (pile->no)
- {
- c = pile->card[pile->no - 1];
-
- pile->no--;
-
- if (pile->no)
- {
- pile->card = realloc(pile->card, sizeof *pile->card * pile->no);
-
- if (!pile->card)
- {
- Fatal("Failed to reallocate memory");
- }
- }
- else
- {
- free(pile->card);
- pile->card = NULL;
- }
- }
- else
- {
- free(pile->card);
- pile->card = NULL;
- }
-
- return c;
-}
-
-static Card TopOfPile(Pile *pile)
-{
- Card c = {0};
-
- if (pile->no)
- {
- c = pile->card[pile->no - 1];
- }
-
- return c;
-}
-
-static void MoveTopCard(Pile *from, Pile *to)
-{
- Card c;
-
- if (from->no)
- {
- c = PopPile(from);
- AddToPile(to, c);
- }
-}
-
-static void SwapPile(Pile *a, Pile *b)
-{
- Pile t;
-
- t = *a;
- *a = *b;
- *b = t;
-}
-
-static void FreePile(Pile *p)
-{
- if (p->card)
- {
- free(p->card);
- p->card = NULL;
- }
-}
-
-static void Centre(int y, const char *p)
-{
- size_t l = strlen(p);
-
- mvaddstr(y, COLS / 2 - l / 2, p);
-}
-
-static const char *CardName(Card c)
-{
- static char buff[32];
- static const char *num[]=
- {
- "ERR",
- " A",
- " 2",
- " 3",
- " 4",
- " 5",
- " 6",
- " 7",
- " 8",
- " 9",
- "10",
- " J",
- " Q",
- " K"
- };
-
- sprintf(buff, "%s%c", num[c.value], c.suit);
-
- return buff;
-}
-
-static void DrawCard(int y, int x, int face_down, Card c)
-{
- if (c.suit == NoSuit)
- {
- mvaddstr(y, x, " ");
- }
- else
- {
- if (face_down)
- {
- mvaddstr(y, x, "###");
- }
- else
- {
- if (c.suit == Spade || c.suit == Club)
- {
- attron(A_REVERSE);
- }
-
- mvaddstr(y, x, CardName(c));
-
- if (c.suit == Spade || c.suit == Club)
- {
- attroff(A_REVERSE);
- }
- }
- }
-}
-
-static double DRand()
-{
- return (double)(rand() % 1000) / 1000.0;
-}
-
-static void WinScreen()
-{
- static const char *text[] =
- {
- "# # ## # # # # ## # #",
- " # # # # # # # # # # ## #",
- " # # # # # # # # # # # ##",
- " # # # # # ## ## # # # #",
- " # ## ## # # ## # #",
- NULL,
- };
-
- static const int NO_STAR = 100;
-
- typedef struct
- {
- double x,y,yi;
- } Star;
-
- Star *star;
-
- int f;
-
- star = malloc(sizeof *star * NO_STAR);
-
- if (!star)
- {
- Fatal("Memory allocation failed");
- }
-
- for(f = 0; f < NO_STAR; f++)
- {
- star[f].x = rand() % COLS;
- star[f].y = rand() % LINES;
-
- do
- {
- star[f].yi = DRand() * 2;
- } while(star[f].yi == 0);
- }
-
- halfdelay(1);
-
- erase();
-
- while(getch() != ' ')
- {
- for(f = 0; f < NO_STAR; f++)
- {
- mvaddch(star[f].y, star[f].x, ' ');
-
- star[f].y -= star[f].yi;
-
- if (star[f].y < 0)
- {
- star[f].x = rand() % COLS;
- star[f].y = LINES - 1;
-
- do
- {
- star[f].yi = DRand() * 2;
- } while(star[f].yi == 0);
- }
- }
-
- for(f = 0; f < NO_STAR; f++)
- {
- mvaddch(star[f].y, star[f].x, '.');
- }
-
- for(f = 0 ; text[f]; f++)
- {
- int x = COLS / 2 - strlen(text[f]) / 2;
- int i;
-
- for(i = 0; text[f][i]; i++)
- {
- if (text[f][i] != ' ')
- {
- mvaddch(f + 4, x++, text[f][i]);
- }
- else
- {
- x++;
- }
- }
- }
-
- Centre(f + 7, "PRESS SPACE");
-
- refresh();
- }
-
- nocbreak();
- cbreak();
- erase();
-
- free(star);
-}
-
-static int CanCardSitOnTop(Card card, Card on)
-{
- int ret = FALSE;
-
- if (card.suit != NoSuit && on.suit != NoSuit)
- {
- if (card.value == on.value - 1)
- {
- switch(card.suit)
- {
- case Spade:
- case Club:
- ret = (on.suit == Heart || on.suit == Diamond);
- break;
-
- case Heart:
- case Diamond:
- ret = (on.suit == Spade || on.suit == Club);
- break;
-
- case NoSuit:
- break;
- }
- }
- }
-
- return ret;
-}
-
-static int PutCardOnSuitPile(Pile *from, Pile *hearts, Pile *diamonds,
- Pile *spades, Pile *clubs)
-{
- Card c;
- Pile *p;
- int move = FALSE;
-
- c = TopOfPile(from);
-
- if (c.suit != NoSuit)
- {
- switch(c.suit)
- {
- case Heart:
- p = hearts;
- break;
- case Diamond:
- p = diamonds;
- break;
- case Spade:
- p = spades;
- break;
- case Club:
- p = clubs;
- break;
- default:
- p = NULL;
- break;
- }
-
- if (p->no)
- {
- if (c.value == TopOfPile(p).value + 1)
- {
- move = TRUE;
- }
- }
- else
- {
- if (c.value == 1 )
- {
- move = TRUE;
- }
- }
-
- if (move)
- {
- MoveTopCard(from, p);
- }
- }
-
- return move;
-}
-
-static void RevealCard(Pile *column_down, Pile *column_up)
-{
- if (column_up->no == 0)
- {
- if (column_down->no)
- {
- InsertBottomOfPile(column_up, PopPile(column_down));
- }
- }
-}
-
-static void KlondikeHelp(void)
-{
- static const char *text[] =
- {
- "Use the cursor keys to move the cursor around.",
- "",
- "Press RETURN to select a bunch of cards to move.",
- "Press RETURN again when you are where you want to move the cards.",
- "",
- "Use space to draw the next set of cards.",
- "",
- "Use 'S' to move a card from the drawn cards to the current column.",
- "",
- "Use 'P' to put the current card on the suits piles.",
- "If invalid it will attempt to move the card from the drawn pile.",
- "",
- "Press '1', '2', '3' or '4' to move the top card from the hearts, ",
- "diamonds, spades or clubs suit pile respectively back onto the board.",
- "",
- "Press 'Q' to quit. You'll be asked if you want to see the cards.",
- "",
- "",
- "Press SPACE to continue.",
- NULL
- };
-
- int y = 2;
- int f;
-
- erase();
-
- for(f = 0; text[f]; f++)
- {
- Centre(y++, text[f]);
- }
-
- refresh();
-
- while(getch() != ' ');
-}
-
-static void Klondike(int draw)
-{
- Deck deck;
- Pile pile = {0};
- Pile turned = {0};
- Pile hearts = {0};
- Pile diamonds = {0};
- Pile clubs = {0};
- Pile spades = {0};
- Pile column_down[7] = {{0}};
- Pile column_up[7] = {{0}};
- int f;
- int n;
- int i;
- int won = FALSE;
- int quit = FALSE;
- int show = FALSE;
- int pos_x = 0;
- int pos_y = 0;
- int move_pos_x = -1;
- int move_pos_y = -1;
-
- Init(deck);
- Shuffle(deck);
-
- i = 0;
-
- for(f = 0; f < 7; f++)
- {
- for(n = 0; n < f; n++)
- {
- AddToPile(&column_down[f], deck[i++]);
- }
-
- AddToPile(&column_up[f], deck[i++]);
- }
-
- while(i < 52)
- {
- AddToPile(&pile, deck[i++]);
- }
-
- while(!quit && !won)
- {
- Card c = {0};
- int key = 0;
-
- erase();
-
- DrawCard(0, 0, TRUE, TopOfPile(&pile));
- DrawCard(0, 4, FALSE, TopOfPile(&turned));
-
- DrawCard(0, 10, FALSE, TopOfPile(&hearts));
- DrawCard(0, 15, FALSE, TopOfPile(&diamonds));
- DrawCard(0, 20, FALSE, TopOfPile(&spades));
- DrawCard(0, 25, FALSE, TopOfPile(&clubs));
-
- for(f = 0; f < 7; f++)
- {
- for(n = 0; n < column_down[f].no; n++)
- {
- DrawCard(2 + n, 1 + f * 5, TRUE, column_down[f].card[n]);
- }
-
- for(n = 0; n < column_up[f].no; n++)
- {
- DrawCard(2 + column_down[f].no + n, 1 + f * 5,
- FALSE, column_up[f].card[n]);
- }
- }
-
- if (move_pos_x != -1)
- {
- mvaddch(2 + column_down[move_pos_x].no + move_pos_y,
- move_pos_x * 5, '*');
- mvaddch(2 + column_down[move_pos_x].no + move_pos_y,
- move_pos_x * 5 + 4, '*');
- }
-
- if (!column_up[pos_x].no && !column_down[pos_x].no)
- {
- mvaddch(2, pos_x * 5, '>');
- mvaddch(2, pos_x * 5 + 4, '<');
- }
- else
- {
- mvaddch(2 + column_down[pos_x].no + pos_y, pos_x * 5, '>');
- mvaddch(2 + column_down[pos_x].no + pos_y, pos_x * 5 + 4, '<');
- }
-
- if (hearts.no == 13 && diamonds.no == 13 &&
- spades.no == 13 && clubs.no == 13)
- {
- won = TRUE;
- }
-
- refresh();
-
- if (!won)
- {
- key = getch();
- }
-
- switch(key)
- {
- case ' ':
- if (pile.no)
- {
- for(f = 0; f < draw; f++)
- {
- MoveTopCard(&pile, &turned);
- }
- }
- else
- {
- SwapPile(&pile, &turned);
- }
- break;
-
- case 'S':
- case 's':
- c = TopOfPile(&turned);
-
- if (c.value == 13 && column_up[pos_x].no == 0 &&
- column_down[pos_x].no == 0)
- {
- MoveTopCard(&turned, &column_up[pos_x]);
- }
- else
- {
- if (CanCardSitOnTop(c, TopOfPile(&column_up[pos_x])))
- {
- MoveTopCard(&turned, &column_up[pos_x]);
- pos_y++;
- }
- }
- break;
-
- case 'P':
- case 'p':
- if (PutCardOnSuitPile(&column_up[pos_x],
- &hearts, &diamonds, &spades, &clubs))
- {
- RevealCard(&column_down[pos_x], &column_up[pos_x]);
-
- pos_y--;
-
- if (pos_y < 0)
- {
- pos_y = 0;
- }
- }
- else
- {
- PutCardOnSuitPile(&turned, &hearts, &diamonds,
- &spades, &clubs);
- }
- break;
-
- case 'Q':
- case 'q':
- {
- int k;
-
- quit = TRUE;
- Centre(LINES-1, "Show cards?");
- refresh();
- k = getch();
- show = (k == 'y' || k == 'Y');
- break;
- }
-
- case 10:
- if (move_pos_x == -1)
- {
- move_pos_x = pos_x;
- move_pos_y = pos_y;
- }
- else
- {
- int can_move = FALSE;
-
- if (column_up[move_pos_x].no &&
- column_up[move_pos_x].card[move_pos_y].value == 13 &&
- column_up[pos_x].no == 0 && column_down[pos_x].no == 0)
- {
- can_move = TRUE;
- }
- else
- {
- if (column_up[move_pos_x].no &&
- CanCardSitOnTop
- (column_up[move_pos_x].card[move_pos_y],
- TopOfPile(&column_up[pos_x])))
- {
- can_move = TRUE;
- }
- }
-
- if (can_move)
- {
- Pile temp = {0};
-
- while(column_up[move_pos_x].no > move_pos_y)
- {
- MoveTopCard(&column_up[move_pos_x],
- &temp);
- }
-
- while(temp.no)
- {
- MoveTopCard(&temp,
- &column_up[pos_x]);
- }
-
- RevealCard(&column_down[move_pos_x],
- &column_up[move_pos_x]);
- }
-
- move_pos_x = -1;
- move_pos_y = -1;
- }
- break;
-
- case '1':
- if (CanCardSitOnTop(TopOfPile(&hearts),
- TopOfPile(&column_up[pos_x])))
- {
- MoveTopCard(&hearts, &column_up[pos_x]);
- }
- break;
-
- case '2':
- if (CanCardSitOnTop(TopOfPile(&diamonds),
- TopOfPile(&column_up[pos_x])))
- {
- MoveTopCard(&diamonds, &column_up[pos_x]);
- }
- break;
-
- case '3':
- if (CanCardSitOnTop(TopOfPile(&spades),
- TopOfPile(&column_up[pos_x])))
- {
- MoveTopCard(&spades, &column_up[pos_x]);
- }
- break;
-
- case '4':
- if (CanCardSitOnTop(TopOfPile(&clubs),
- TopOfPile(&column_up[pos_x])))
- {
- MoveTopCard(&clubs, &column_up[pos_x]);
- }
- break;
-
- case KEY_LEFT:
- if (pos_x)
- {
- pos_x--;
- pos_y = column_up[pos_x].no - 1;
-
- if (pos_y < 0)
- {
- pos_y = 0;
- }
- }
- break;
-
- case KEY_RIGHT:
- if (pos_x < 6)
- {
- pos_x++;
- pos_y = column_up[pos_x].no - 1;
-
- if (pos_y < 0)
- {
- pos_y = 0;
- }
- }
- break;
-
- case KEY_UP:
- if (pos_y)
- {
- pos_y--;
- }
- break;
-
- case KEY_DOWN:
- if (pos_y < column_up[pos_x].no - 1)
- {
- pos_y++;
- }
- break;
-
- case '?':
- KlondikeHelp();
- break;
-
- default:
- break;
- }
- }
-
- if (show)
- {
- for(f = 0; f < 7; f++)
- {
- for(n = 0; n < column_down[f].no; n++)
- {
- DrawCard(2 + n, 1 + f * 5, FALSE, column_down[f].card[n]);
- }
-
- for(n = 0; n < column_up[f].no; n++)
- {
- DrawCard(2 + column_down[f].no + n, 1 + f * 5,
- FALSE, column_up[f].card[n]);
- }
- }
-
- Centre(LINES - 1, "Press any key");
- refresh();
- getch();
- }
-
- if (won)
- {
- WinScreen();
- }
-
- FreePile(&pile);
- FreePile(&turned);
- FreePile(&hearts);
- FreePile(&diamonds);
- FreePile(&clubs);
- FreePile(&spades);
- for(f = 0; f < 7; f++)
- {
- FreePile(&column_down[f]);
- FreePile(&column_up[f]);
- }
-}
+#include "deck.h"
+#include "pile.h"
+#include "util.h"
+#include "klondike.h"
int main(int argc, char *argv[])
{