|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
#include <img.h>
|
|
Ivan Mahonin |
7d8000 |
#include <snd.h>
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
#include <ctype.h>
|
|
Ivan Mahonin |
7d8000 |
#include <dirent.h>
|
|
Ivan Mahonin |
7d8000 |
|
|
 |
5c4215 |
#define MAXSIZE 40
|
|
 |
5c4215 |
#define MAXCOUNT (MAXSIZE*MAXSIZE)
|
|
 |
5c4215 |
#define VBASE 8 // must be even
|
|
 |
5c4215 |
#define HBASE 10 // must be even
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
c88cf2 |
#define LETTERSRATIO 7
|
|
Ivan Mahonin |
7d8000 |
#define MAXLETTERS 256
|
|
Ivan Mahonin |
7d8000 |
#define MAXSOUNDS 16
|
|
Ivan Mahonin |
7d8000 |
#define RMTIME 1.0
|
|
Ivan Mahonin |
7d8000 |
#define EXTIME 2.0
|
|
Ivan Mahonin |
7d8000 |
#define SNDRATE 44100
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
typedef struct {
|
|
Ivan Mahonin |
7d8000 |
Image src;
|
|
Ivan Mahonin |
7d8000 |
XImage *x;
|
|
Ivan Mahonin |
7d8000 |
} ImageEx;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
typedef struct {
|
|
Ivan Mahonin |
de1fb3 |
ImageEx a, b;
|
|
Ivan Mahonin |
de1fb3 |
} ImagePair;
|
|
Ivan Mahonin |
de1fb3 |
|
|
Ivan Mahonin |
de1fb3 |
typedef struct {
|
|
Ivan Mahonin |
de1fb3 |
ImagePair glyphs[4];
|
|
Ivan Mahonin |
7d8000 |
int glyphsCount;
|
|
Ivan Mahonin |
7d8000 |
Sound sounds[MAXSOUNDS];
|
|
Ivan Mahonin |
7d8000 |
int soundsCount;
|
|
Ivan Mahonin |
de1fb3 |
ImagePair *g[4];
|
|
Ivan Mahonin |
7d8000 |
} Letter;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
typedef struct {
|
|
Ivan Mahonin |
7d8000 |
int r, c;
|
|
Ivan Mahonin |
7d8000 |
} Pos;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
typedef struct {
|
|
Ivan Mahonin |
7d8000 |
int len;
|
|
Ivan Mahonin |
7d8000 |
Pos p[4];
|
|
Ivan Mahonin |
7d8000 |
} Track;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
typedef struct {
|
|
Ivan Mahonin |
7d8000 |
Letter *l;
|
|
Ivan Mahonin |
de1fb3 |
ImagePair *g;
|
|
Ivan Mahonin |
7d8000 |
} Cell;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
 |
5c4215 |
int cols = 4;
|
|
 |
5c4215 |
int rows = 4;
|
|
 |
5c4215 |
int count = 4*4;
|
|
 |
5c4215 |
|
|
Ivan Mahonin |
7d8000 |
Letter menuLetter;
|
|
Ivan Mahonin |
7d8000 |
Letter letters[MAXLETTERS];
|
|
Ivan Mahonin |
7d8000 |
int lettersCount;
|
|
 |
5c4215 |
int baseCellWidth = 1;
|
|
 |
5c4215 |
int baseCellHeight = 1;
|
|
Ivan Mahonin |
7d8000 |
int cellWidth = 1;
|
|
Ivan Mahonin |
7d8000 |
int cellHeight = 1;
|
|
Ivan Mahonin |
7d8000 |
|
|
 |
5c4215 |
Cell board[MAXSIZE][MAXSIZE];
|
|
Ivan Mahonin |
7d8000 |
Pos hover = { -1, -1 };
|
|
Ivan Mahonin |
7d8000 |
Pos selected = { -1, -1 };
|
|
 |
5c4215 |
Track tracks[MAXCOUNT];
|
|
Ivan Mahonin |
7d8000 |
int tracksCount;
|
|
Ivan Mahonin |
7d8000 |
int glyphsMask = 0;
|
|
Ivan Mahonin |
7d8000 |
int mode;
|
|
Ivan Mahonin |
86bfaf |
Letter *hintLetter;
|
|
Ivan Mahonin |
7d8000 |
int back;
|
|
Ivan Mahonin |
de1fb3 |
int mute;
|
|
Ivan Mahonin |
7d8000 |
int ox, oy, cw, ch;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
ImageEx bgtex;
|
|
Ivan Mahonin |
7d8000 |
ImageEx starttex;
|
|
Ivan Mahonin |
7d8000 |
ImageEx hinttex;
|
|
Ivan Mahonin |
7d8000 |
ImageEx backtex[3];
|
|
Ivan Mahonin |
de1fb3 |
ImageEx sndtex[3];
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
void imgExFree(ImageEx *img) {
|
|
Ivan Mahonin |
de1fb3 |
if (!img) return;
|
|
Ivan Mahonin |
7d8000 |
if (img->x) XDestroyImage(img->x);
|
|
Ivan Mahonin |
7d8000 |
imgFree(&img->src);
|
|
Ivan Mahonin |
7d8000 |
*img = (ImageEx){};
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
de1fb3 |
void imgExResample(ImageEx *img, int w, int h) {
|
|
Ivan Mahonin |
7d8000 |
if (!imgValid(img->src) || w <= 0 || h <= 0) return;
|
|
Ivan Mahonin |
7d8000 |
if (img->x && (img->x->width != w || img->x->height != h))
|
|
Ivan Mahonin |
7d8000 |
{ XDestroyImage(img->x); img->x = NULL; }
|
|
Ivan Mahonin |
7d8000 |
if (!img->x) {
|
|
Ivan Mahonin |
7d8000 |
Image tmp = imgResample(img->src, w, h);
|
|
Ivan Mahonin |
7d8000 |
imgDivA(tmp);
|
|
Ivan Mahonin |
7d8000 |
img->x = imgToX(&tmp);
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
de1fb3 |
}
|
|
Ivan Mahonin |
de1fb3 |
|
|
Ivan Mahonin |
de1fb3 |
|
|
Ivan Mahonin |
de1fb3 |
void imgExDraw(ImageEx *img, int x, int y, int w, int h) {
|
|
Ivan Mahonin |
de1fb3 |
imgExResample(img, w, h);
|
|
Ivan Mahonin |
7d8000 |
if (img->x)
|
|
Ivan Mahonin |
7d8000 |
XPutImage(dpy, drw, gc, img->x, 0, 0, x, y, img->x->width, img->x->height);
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
int imgExLoadTga(ImageEx *img, const char *filename) {
|
|
Ivan Mahonin |
7d8000 |
imgExFree(img);
|
|
Ivan Mahonin |
7d8000 |
img->src = imgLoadTga(filename);
|
|
Ivan Mahonin |
7d8000 |
imgMultA(img->src);
|
|
Ivan Mahonin |
7d8000 |
return imgValid(img->src);
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
de1fb3 |
void imgPairFree(ImagePair *img) {
|
|
Ivan Mahonin |
de1fb3 |
if (!img) return;
|
|
Ivan Mahonin |
de1fb3 |
imgExFree(&img->a);
|
|
Ivan Mahonin |
de1fb3 |
imgExFree(&img->b);
|
|
Ivan Mahonin |
de1fb3 |
}
|
|
Ivan Mahonin |
de1fb3 |
|
|
Ivan Mahonin |
de1fb3 |
|
|
Ivan Mahonin |
de1fb3 |
void imgPairDraw(ImagePair *img, int mode, int x, int y, int w, int h) {
|
|
Ivan Mahonin |
de1fb3 |
imgExResample(mode ? &img->a : &img->b, w, h);
|
|
Ivan Mahonin |
de1fb3 |
imgExDraw(mode ? &img->b : &img->a, x, y, w, h);
|
|
Ivan Mahonin |
de1fb3 |
}
|
|
Ivan Mahonin |
de1fb3 |
|
|
Ivan Mahonin |
de1fb3 |
|
|
Ivan Mahonin |
7d8000 |
void clearBoard() {
|
|
Ivan Mahonin |
de1fb3 |
if (mute != 1) mute = 0;
|
|
Ivan Mahonin |
7d8000 |
mode = 0;
|
|
Ivan Mahonin |
7d8000 |
back = 0;
|
|
Ivan Mahonin |
86bfaf |
hintLetter = NULL;
|
|
Ivan Mahonin |
7d8000 |
memset(tracks, 0, sizeof(tracks));
|
|
Ivan Mahonin |
7d8000 |
memset(board, 0, sizeof(board));
|
|
Ivan Mahonin |
7d8000 |
tracksCount = 0;
|
|
Ivan Mahonin |
7d8000 |
selected = (Pos){ -1, -1 };
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
void clearSounds() {
|
|
Ivan Mahonin |
7d8000 |
for(int i = 0; i < lettersCount; ++i)
|
|
Ivan Mahonin |
7d8000 |
for(int j = 0; j < letters[i].soundsCount; ++i)
|
|
Ivan Mahonin |
7d8000 |
sndFree(&letters[i].sounds[j]);
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
void clearLetters() {
|
|
Ivan Mahonin |
7d8000 |
clearBoard();
|
|
Ivan Mahonin |
7d8000 |
clearSounds();
|
|
Ivan Mahonin |
7d8000 |
for(int i = 0; i < lettersCount; ++i)
|
|
Ivan Mahonin |
7d8000 |
for(int j = 0; j < letters[i].glyphsCount; ++j)
|
|
Ivan Mahonin |
de1fb3 |
imgPairFree(&letters[i].glyphs[j]);
|
|
Ivan Mahonin |
7d8000 |
memset(letters, 0, sizeof(letters));
|
|
Ivan Mahonin |
7d8000 |
memset(&menuLetter, 0, sizeof(menuLetter));
|
|
Ivan Mahonin |
7d8000 |
lettersCount = 0;
|
|
Ivan Mahonin |
7d8000 |
cellWidth = cellHeight = 1;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
de1fb3 |
int loadLetters(const char *filename, const char *filesel, int rows, int cols) {
|
|
Ivan Mahonin |
7d8000 |
clearLetters();
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
Image img = imgLoadTga(filename);
|
|
Ivan Mahonin |
7d8000 |
if (!imgValid(img))
|
|
Ivan Mahonin |
7d8000 |
return 0;
|
|
Ivan Mahonin |
7d8000 |
int ww = img.w/cols/2;
|
|
Ivan Mahonin |
7d8000 |
int hh = img.h/rows/2;
|
|
Ivan Mahonin |
7d8000 |
if (!ww || !hh)
|
|
Ivan Mahonin |
7d8000 |
return LOGERR("loadLetters: image too small (%dx%d): %s", img.w, img.h, filename), imgFree(&img), 0;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
de1fb3 |
Image imgsel = imgLoadTga(filesel);
|
|
Ivan Mahonin |
de1fb3 |
if (!imgValid(imgsel))
|
|
Ivan Mahonin |
de1fb3 |
return imgFree(&img), 0;
|
|
Ivan Mahonin |
de1fb3 |
int wws = imgsel.w/cols/2;
|
|
Ivan Mahonin |
de1fb3 |
int hhs = imgsel.h/rows/2;
|
|
Ivan Mahonin |
de1fb3 |
if (!wws || !hhs)
|
|
Ivan Mahonin |
de1fb3 |
return LOGERR("loadLetters: image too small (%dx%d): %s", imgsel.w, imgsel.h, filesel), imgFree(&img), imgFree(&imgsel), 0;
|
|
Ivan Mahonin |
de1fb3 |
|
|
Ivan Mahonin |
7d8000 |
imgMultA(img);
|
|
Ivan Mahonin |
7d8000 |
Letter *letter = letters;
|
|
Ivan Mahonin |
7d8000 |
for(int r = 0; r < rows; ++r)
|
|
Ivan Mahonin |
7d8000 |
for(int c = 0; c < cols; ++c)
|
|
Ivan Mahonin |
7d8000 |
{
|
|
Ivan Mahonin |
7d8000 |
for(int rr = 0; rr < 2; ++rr)
|
|
Ivan Mahonin |
7d8000 |
for(int cc = 0; cc < 2; ++cc) {
|
|
Ivan Mahonin |
7d8000 |
Image sub = imgSub(img, (c*2 + cc)*ww, (r*2 + rr)*hh, ww, hh);
|
|
Ivan Mahonin |
7d8000 |
if (!imgHasPicture(sub))
|
|
Ivan Mahonin |
7d8000 |
{ imgFree(&sub); continue; }
|
|
Ivan Mahonin |
de1fb3 |
letter->glyphs[ letter->glyphsCount ].a.src = sub;
|
|
Ivan Mahonin |
de1fb3 |
letter->glyphs[ letter->glyphsCount ].b.src = imgSub(imgsel, (c*2 + cc)*wws, (r*2 + rr)*hhs, wws, hhs);
|
|
Ivan Mahonin |
de1fb3 |
++letter->glyphsCount;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
if (letter->glyphsCount > menuLetter.glyphsCount) menuLetter = *letter;
|
|
Ivan Mahonin |
7d8000 |
if (letter->glyphsCount > 0) ++letter;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
lettersCount = letter - letters;
|
|
 |
5c4215 |
baseCellWidth = wws;
|
|
 |
5c4215 |
baseCellHeight = hhs;
|
|
Ivan Mahonin |
7d8000 |
cellWidth = ww;
|
|
Ivan Mahonin |
7d8000 |
cellHeight = hh;
|
|
Ivan Mahonin |
7d8000 |
assert(menuLetter.glyphsCount == 4);
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
imgFree(&img);
|
|
Ivan Mahonin |
7d8000 |
return 1;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
void loadSounds(const char *path) {
|
|
Ivan Mahonin |
7d8000 |
DIR *dir = opendir(path);
|
|
Ivan Mahonin |
7d8000 |
if (!dir) return;
|
|
Ivan Mahonin |
7d8000 |
size_t pl = strlen(path);
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
char buf[1024];
|
|
Ivan Mahonin |
7d8000 |
while(1) {
|
|
Ivan Mahonin |
7d8000 |
struct dirent *e = readdir(dir);
|
|
Ivan Mahonin |
7d8000 |
if (!e) break;
|
|
Ivan Mahonin |
7d8000 |
size_t nl = strlen(e->d_name);
|
|
Ivan Mahonin |
7d8000 |
if (nl < 4 || pl + nl + 1 >= sizeof(buf)) continue;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
const char *ex = e->d_name + nl - 4;
|
|
Ivan Mahonin |
7d8000 |
if ( ex[0] != '.'
|
|
Ivan Mahonin |
7d8000 |
|| tolower(ex[1]) != 'r'
|
|
Ivan Mahonin |
7d8000 |
|| tolower(ex[2]) != 'a'
|
|
Ivan Mahonin |
7d8000 |
|| tolower(ex[3]) != 'w' ) continue;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
int index = atoi(e->d_name);
|
|
Ivan Mahonin |
7d8000 |
if (index <= 0 || index > lettersCount) continue;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
Letter *l = &letters[index-1];
|
|
Ivan Mahonin |
7d8000 |
if (l->soundsCount >= MAXSOUNDS) continue;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
sprintf(buf, "%s/%s", path, e->d_name);
|
|
Ivan Mahonin |
7d8000 |
l->sounds[l->soundsCount] = sndLoadRaw(buf, SNDRATE);
|
|
Ivan Mahonin |
7d8000 |
//l->sounds[l->soundsCount] = sndGen(SNDRATE, 100, SNDRATE);
|
|
Ivan Mahonin |
7d8000 |
if (sndValid(l->sounds[l->soundsCount])) ++l->soundsCount;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
closedir(dir);
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
void shuffleLetters(int glyps) {
|
|
Ivan Mahonin |
7d8000 |
for(int i = 0; i < lettersCount; ++i) {
|
|
Ivan Mahonin |
7d8000 |
int j = rand()%(lettersCount - i) + i;
|
|
Ivan Mahonin |
7d8000 |
if (j != i) { Letter l = letters[i]; letters[i] = letters[j]; letters[j] = l; }
|
|
Ivan Mahonin |
7d8000 |
Letter *l = &letters[i];
|
|
Ivan Mahonin |
7d8000 |
assert(l->glyphsCount > 0);
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
int gc = 0;
|
|
Ivan Mahonin |
de1fb3 |
ImagePair *g[4] = {};
|
|
Ivan Mahonin |
7d8000 |
for(int j = 0; j < l->glyphsCount; ++j)
|
|
Ivan Mahonin |
7d8000 |
if (glyps & (1 << j)) g[gc++] = &l->glyphs[j];
|
|
Ivan Mahonin |
7d8000 |
if (!gc) g[gc++] = &l->glyphs[0];
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
for(int j = 0; j < gc; ++j) {
|
|
Ivan Mahonin |
7d8000 |
int k = rand()%(gc - j) + j;
|
|
Ivan Mahonin |
de1fb3 |
if (k != j) { ImagePair *a = g[j]; g[j] = g[k]; g[k] = a; }
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
for(int j = 0; j < 4; ++j)
|
|
Ivan Mahonin |
7d8000 |
l->g[j] = g[j%gc];
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
for(int j = 0; j < 4; ++j) {
|
|
Ivan Mahonin |
7d8000 |
int k = rand()%(4 - j) + j;
|
|
Ivan Mahonin |
de1fb3 |
if (k != j) { ImagePair *g = l->g[j]; l->g[j] = l->g[k]; l->g[k] = g; }
|
|
Ivan Mahonin |
7d8000 |
assert(l->g[j]);
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
 |
5c4215 |
void calcSize() {
|
|
 |
5c4215 |
if (winW*baseCellHeight < baseCellWidth*winH) {
|
|
 |
5c4215 |
cols = HBASE; // portrait
|
|
 |
5c4215 |
rows = winH*cols*baseCellWidth/(winW*baseCellHeight);
|
|
 |
5c4215 |
} else {
|
|
 |
5c4215 |
rows = VBASE; // landscape
|
|
 |
5c4215 |
cols = winW*rows*baseCellHeight/(winH*baseCellWidth);
|
|
 |
5c4215 |
}
|
|
 |
5c4215 |
cols -= 4; // place for buttons
|
|
 |
5c4215 |
rows -= 2;
|
|
 |
5c4215 |
if (rows < 1) rows = 1;
|
|
 |
5c4215 |
if (cols < 1) cols = 1;
|
|
 |
5c4215 |
if (rows > MAXSIZE) rows = MAXSIZE;
|
|
 |
5c4215 |
if (cols > MAXSIZE) cols = MAXSIZE;
|
|
 |
5c4215 |
count = rows*cols;
|
|
 |
5c4215 |
}
|
|
 |
5c4215 |
|
|
 |
5c4215 |
|
|
Ivan Mahonin |
7d8000 |
void simpleBoard() {
|
|
Ivan Mahonin |
7d8000 |
clearBoard();
|
|
 |
5c4215 |
calcSize();
|
|
 |
5c4215 |
for(int i = 0; i < count; ++i) {
|
|
Ivan Mahonin |
7d8000 |
Letter *l = &letters[i%lettersCount];
|
|
 |
5c4215 |
board[i/cols][i%cols].l = l;
|
|
 |
5c4215 |
board[i/cols][i%cols].g = &l->glyphs[1];
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
mode = 1;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
c88cf2 |
void generateBoard(int glyphsMask) {
|
|
Ivan Mahonin |
7d8000 |
clearBoard();
|
|
 |
5c4215 |
calcSize();
|
|
Ivan Mahonin |
7d8000 |
shuffleLetters(glyphsMask);
|
|
Ivan Mahonin |
7d8000 |
|
|
 |
5c4215 |
int indices[MAXCOUNT];
|
|
 |
5c4215 |
for(int i = 0; i < count; ++i) indices[i] = i;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
c88cf2 |
int maxLetters = count/LETTERSRATIO + 1;
|
|
Ivan Mahonin |
7d8000 |
int lc = lettersCount < maxLetters ? lettersCount : maxLetters;
|
|
 |
5c4215 |
for(int i = 0; i < count; ++i) {
|
|
 |
5c4215 |
int j = rand()%(count - i) + i;
|
|
Ivan Mahonin |
7d8000 |
int id = indices[j]; indices[j] = indices[i]; indices[i] = id;
|
|
Ivan Mahonin |
7d8000 |
Letter *l = &letters[ (id/4)%lc ];
|
|
 |
5c4215 |
board[i/cols][i%cols].l = l;
|
|
 |
5c4215 |
board[i/cols][i%cols].g = l->g[id%4];
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
mode = 1;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
Letter* get(Pos p)
|
|
 |
5c4215 |
{ return p.r >= 0 && p.r < rows && p.c >= 0 && p.c < cols ? board[p.r][p.c].l : NULL; }
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
int findSubTrack1(Track *t, Pos b) {
|
|
Ivan Mahonin |
7d8000 |
Pos p = t->p[t->len - 1];
|
|
Ivan Mahonin |
7d8000 |
//printf(" -- -- ft1: %d %d -> %d %d\n", p.r, p.c, b.r, b.c);
|
|
Ivan Mahonin |
7d8000 |
if (p.c == b.c && p.r < b.r) { for(++p.r; p.r != b.r; ++p.r) if (get(p)) return 0; } else
|
|
Ivan Mahonin |
7d8000 |
if (p.c == b.c && p.r > b.r) { for(--p.r; p.r != b.r; --p.r) if (get(p)) return 0; } else
|
|
Ivan Mahonin |
7d8000 |
if (p.r == b.r && p.c < b.c) { for(++p.c; p.c != b.c; ++p.c) if (get(p)) return 0; } else
|
|
Ivan Mahonin |
7d8000 |
if (p.r == b.r && p.c > b.c) { for(--p.c; p.c != b.c; --p.c) if (get(p)) return 0; } else return 0;
|
|
Ivan Mahonin |
7d8000 |
t->p[t->len++] = p;
|
|
Ivan Mahonin |
7d8000 |
return 1;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
int findSubTrack2(Track *t, Pos b, int horz) {
|
|
Ivan Mahonin |
7d8000 |
Pos *p = &t->p[t->len];
|
|
Ivan Mahonin |
7d8000 |
*p = t->p[t->len - 1];
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
//printf(" -- ft2: %d %d -> %d %d %s\n", p->r, p->c, b.r, b.c, horz ? "horz" : "vert");
|
|
Ivan Mahonin |
7d8000 |
if (p->c == b.c || p->r == b.r) return findSubTrack1(t, b);
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
++t->len;
|
|
Ivan Mahonin |
7d8000 |
if (horz) {
|
|
Ivan Mahonin |
7d8000 |
if (p->c < b.c) { for(++p->c; p->c != b.c; ++p->c) if (get(*p)) break; }
|
|
Ivan Mahonin |
7d8000 |
else { for(--p->c; p->c != b.c; --p->c) if (get(*p)) break; }
|
|
Ivan Mahonin |
7d8000 |
} else {
|
|
Ivan Mahonin |
7d8000 |
if (p->r < b.r) { for(++p->r; p->r != b.r; ++p->r) if (get(*p)) break; }
|
|
Ivan Mahonin |
7d8000 |
else { for(--p->r; p->r != b.r; --p->r) if (get(*p)) break; }
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
if (!get(*p) && findSubTrack1(t, b)) return 1;
|
|
Ivan Mahonin |
7d8000 |
--t->len;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
return 0;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
int findSubTrack3(Track *t, Pos b) {
|
|
Ivan Mahonin |
7d8000 |
Pos p0 = t->p[t->len - 1];
|
|
Ivan Mahonin |
7d8000 |
Pos *p = &t->p[t->len];
|
|
Ivan Mahonin |
7d8000 |
if (p->c == b.c && p->r == b.r) return 0;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
//printf("ft3: %d %d -> %d %d\n", p0.r, p0.c, b.r, b.c);
|
|
Ivan Mahonin |
7d8000 |
if (findSubTrack2(t, b, 0)) return 1;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
++t->len;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
*p = p0;
|
|
 |
5c4215 |
for(++p->c; p->c <= cols; ++p->c)
|
|
Ivan Mahonin |
7d8000 |
if (get(*p)) break; else
|
|
Ivan Mahonin |
7d8000 |
if (findSubTrack2(t, b, 0)) return 1;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
*p = p0;
|
|
Ivan Mahonin |
7d8000 |
for(--p->c; p->c >= -1; --p->c)
|
|
Ivan Mahonin |
7d8000 |
if (get(*p)) break; else
|
|
Ivan Mahonin |
7d8000 |
if (findSubTrack2(t, b, 0)) return 1;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
*p = p0;
|
|
 |
5c4215 |
for(++p->r; p->r <= rows; ++p->r)
|
|
Ivan Mahonin |
7d8000 |
if (get(*p)) break; else
|
|
Ivan Mahonin |
7d8000 |
if (findSubTrack2(t, b, 1)) return 1;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
*p = p0;
|
|
Ivan Mahonin |
7d8000 |
for(--p->r; p->r >= -1; --p->r)
|
|
Ivan Mahonin |
7d8000 |
if (get(*p)) break; else
|
|
Ivan Mahonin |
7d8000 |
if (findSubTrack2(t, b, 1)) return 1;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
--t->len;
|
|
Ivan Mahonin |
7d8000 |
return 0;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
Track findTrack(Pos a, Pos b) {
|
|
Ivan Mahonin |
7d8000 |
Track t = {};
|
|
Ivan Mahonin |
7d8000 |
t.p[t.len++] = a;
|
|
Ivan Mahonin |
7d8000 |
Letter *la = get(a);
|
|
Ivan Mahonin |
7d8000 |
Letter *lb = get(b);
|
|
Ivan Mahonin |
7d8000 |
return la && la == lb && (a.c != b.c || a.r != b.r) && findSubTrack3(&t, b) ? t : (Track){};
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
void hint() {
|
|
Ivan Mahonin |
7d8000 |
if (tracksCount) return;
|
|
Ivan Mahonin |
7d8000 |
|
|
 |
5c4215 |
for(int i = 0; i < count; ++i) {
|
|
 |
5c4215 |
Pos a = { i/cols, i%cols };
|
|
 |
5c4215 |
for(int j = 0; j < count; ++j) {
|
|
 |
5c4215 |
Pos b = { j/cols, j%cols };
|
|
Ivan Mahonin |
7d8000 |
Track t = findTrack(a, b);
|
|
Ivan Mahonin |
7d8000 |
if (t.len)
|
|
Ivan Mahonin |
7d8000 |
tracks[tracksCount++] = t;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
LOGDBG("hint: tracks count: %d", tracksCount);
|
|
Ivan Mahonin |
7d8000 |
if (!tracksCount) return; // beep
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
int i = rand()%tracksCount;
|
|
Ivan Mahonin |
7d8000 |
if (i) tracks[0] = tracks[i];
|
|
Ivan Mahonin |
7d8000 |
tracksCount = 1;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
int init() {
|
|
Ivan Mahonin |
7d8000 |
sndInit();
|
|
Ivan Mahonin |
7d8000 |
srand(time(NULL));
|
|
Ivan Mahonin |
7d8000 |
imgExLoadTga(&bgtex, "data/minas.tga");
|
|
Ivan Mahonin |
7d8000 |
imgExLoadTga(&starttex, "data/start.tga");
|
|
Ivan Mahonin |
7d8000 |
imgExLoadTga(&hinttex, "data/hint.tga");
|
|
Ivan Mahonin |
7d8000 |
imgExLoadTga(&backtex[0], "data/back.tga");
|
|
Ivan Mahonin |
7d8000 |
imgExLoadTga(&backtex[1], "data/back1.tga");
|
|
Ivan Mahonin |
7d8000 |
imgExLoadTga(&backtex[2], "data/back2.tga");
|
|
Ivan Mahonin |
de1fb3 |
imgExLoadTga(&sndtex[0], "data/sound.tga");
|
|
Ivan Mahonin |
de1fb3 |
imgExLoadTga(&sndtex[1], "data/silence.tga");
|
|
Ivan Mahonin |
de1fb3 |
imgExLoadTga(&sndtex[2], "data/sound2.tga");
|
|
Ivan Mahonin |
de1fb3 |
if (!loadLetters("data/letters.tga", "data/letters-sel.tga", 5, 8))
|
|
Ivan Mahonin |
7d8000 |
return LOGERR("init: cannot load letters"), 0;
|
|
Ivan Mahonin |
7d8000 |
loadSounds("data/sounds");
|
|
Ivan Mahonin |
7d8000 |
//simpleBoard();
|
|
Ivan Mahonin |
7d8000 |
return 1;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
void deinit() {
|
|
Ivan Mahonin |
7d8000 |
clearLetters();
|
|
Ivan Mahonin |
7d8000 |
imgExFree(&bgtex);
|
|
Ivan Mahonin |
7d8000 |
imgExFree(&starttex);
|
|
Ivan Mahonin |
7d8000 |
imgExFree(&hinttex);
|
|
Ivan Mahonin |
7d8000 |
imgExFree(&backtex[0]);
|
|
Ivan Mahonin |
7d8000 |
imgExFree(&backtex[1]);
|
|
Ivan Mahonin |
7d8000 |
imgExFree(&backtex[2]);
|
|
Ivan Mahonin |
de1fb3 |
imgExFree(&sndtex[0]);
|
|
Ivan Mahonin |
de1fb3 |
imgExFree(&sndtex[1]);
|
|
Ivan Mahonin |
de1fb3 |
imgExFree(&sndtex[2]);
|
|
Ivan Mahonin |
7d8000 |
sndDeinit();
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
void resize() { }
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
void mouseDown(int x, int y) {
|
|
Ivan Mahonin |
7d8000 |
int mc = (x - ox)/cw;
|
|
Ivan Mahonin |
7d8000 |
int mr = (y - oy)/ch;
|
|
Ivan Mahonin |
7d8000 |
if (x < ox) --mc;
|
|
Ivan Mahonin |
7d8000 |
if (y < oy) --mr;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
if (mode == 0) {
|
|
Ivan Mahonin |
7d8000 |
if (!mr && mc >= 0 && mc < 4) {
|
|
Ivan Mahonin |
7d8000 |
glyphsMask ^= 1 << mc;
|
|
Ivan Mahonin |
7d8000 |
} else
|
|
Ivan Mahonin |
7d8000 |
if (mr == 1 && mc >= 1 && mc <= 2) {
|
|
Ivan Mahonin |
c88cf2 |
generateBoard(glyphsMask);
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
} else {
|
|
Ivan Mahonin |
7d8000 |
if (mc < 0 && mr < 0) {
|
|
Ivan Mahonin |
7d8000 |
if (++back >= 3) clearBoard();
|
|
Ivan Mahonin |
7d8000 |
return;
|
|
Ivan Mahonin |
7d8000 |
} else back = 0;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
86bfaf |
hover.r = hover.c = -1;
|
|
Ivan Mahonin |
86bfaf |
hintLetter = NULL;
|
|
Ivan Mahonin |
86bfaf |
tracksCount = 0;
|
|
 |
5c4215 |
for(int r = 0; r < rows; ++r)
|
|
 |
5c4215 |
for(int c = 0; c < cols; ++c)
|
|
Ivan Mahonin |
86bfaf |
if (!board[r][c].l) board[r][c].g = NULL;
|
|
Ivan Mahonin |
86bfaf |
|
|
 |
5c4215 |
if (mc >= cols && mr >= rows) {
|
|
Ivan Mahonin |
86bfaf |
hintLetter = get(selected);
|
|
Ivan Mahonin |
86bfaf |
if (!hintLetter) hint();
|
|
Ivan Mahonin |
86bfaf |
selected.r = selected.c = -1;
|
|
Ivan Mahonin |
7d8000 |
} else
|
|
 |
5c4215 |
if (mc >= cols && mr < 0) {
|
|
Ivan Mahonin |
de1fb3 |
mute = mute == 1 ? 2 : 1;
|
|
Ivan Mahonin |
de1fb3 |
} else
|
|
 |
5c4215 |
if (mc >= 0 && mr >= 0 && mc < cols && mr < rows) {
|
|
Ivan Mahonin |
7d8000 |
hover.r = mr;
|
|
Ivan Mahonin |
7d8000 |
hover.c = mc;
|
|
Ivan Mahonin |
7d8000 |
Letter *l = get(hover);
|
|
Ivan Mahonin |
de1fb3 |
if (l && l->soundsCount > 0 && mute != 1)
|
|
Ivan Mahonin |
7d8000 |
sndPlay(l->sounds[rand() % l->soundsCount]);
|
|
Ivan Mahonin |
7d8000 |
if (!l || (mr == selected.r && mc == selected.c)) {
|
|
Ivan Mahonin |
7d8000 |
selected.r = selected.c = hover.r = hover.c = -1;
|
|
Ivan Mahonin |
7d8000 |
} else
|
|
Ivan Mahonin |
7d8000 |
if (l == get(selected)) {
|
|
Ivan Mahonin |
7d8000 |
Track t = findTrack(selected, hover);
|
|
Ivan Mahonin |
7d8000 |
if (t.len) {
|
|
Ivan Mahonin |
7d8000 |
Cell *ca = &board[selected.r][selected.c];
|
|
Ivan Mahonin |
7d8000 |
Cell *cb = &board[hover.r][hover.c];
|
|
Ivan Mahonin |
7d8000 |
ca->l = cb->l = NULL;
|
|
Ivan Mahonin |
7d8000 |
tracks[tracksCount++] = t;
|
|
Ivan Mahonin |
7d8000 |
} else {
|
|
Ivan Mahonin |
7d8000 |
selected = hover;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
} else {
|
|
Ivan Mahonin |
7d8000 |
selected = hover;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
} else {
|
|
Ivan Mahonin |
7d8000 |
selected.r = selected.c = hover.r = hover.c = -1;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
void mouseUp() {
|
|
Ivan Mahonin |
86bfaf |
int cnt = 0;
|
|
 |
5c4215 |
for(int r = 0; r < rows; ++r)
|
|
 |
5c4215 |
for(int c = 0; c < cols; ++c)
|
|
Ivan Mahonin |
86bfaf |
if (!board[r][c].l && board[r][c].g)
|
|
Ivan Mahonin |
86bfaf |
{ ++cnt; board[r][c].g = NULL; }
|
|
Ivan Mahonin |
86bfaf |
if (cnt) tracksCount = 0;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
void draw() {
|
|
Ivan Mahonin |
7d8000 |
if (imgValid(bgtex.src)) {
|
|
Ivan Mahonin |
7d8000 |
if (winW*bgtex.src.h > winH*bgtex.src.w) {
|
|
Ivan Mahonin |
7d8000 |
int h = bgtex.src.h*winW/bgtex.src.w;
|
|
Ivan Mahonin |
7d8000 |
imgExDraw(&bgtex, 0, (winH - h)/2, winW, h);
|
|
Ivan Mahonin |
7d8000 |
} else {
|
|
Ivan Mahonin |
7d8000 |
int w = bgtex.src.w*winH/bgtex.src.h;
|
|
Ivan Mahonin |
7d8000 |
imgExDraw(&bgtex, (winW - w)/2, 0, w, winH);
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
if (mode == 0) {
|
|
Ivan Mahonin |
7d8000 |
if (winW*cellHeight*3 < winH*cellWidth*6) {
|
|
Ivan Mahonin |
7d8000 |
cw = winW/6;
|
|
Ivan Mahonin |
7d8000 |
ch = cellHeight*cw/cellWidth;
|
|
Ivan Mahonin |
7d8000 |
} else {
|
|
Ivan Mahonin |
7d8000 |
ch = winH/3;
|
|
Ivan Mahonin |
7d8000 |
cw = cellWidth*ch/cellHeight;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
ox = (winW - cw*4)/2;
|
|
Ivan Mahonin |
7d8000 |
oy = (winH - ch)/2;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
for(int i = 0; i < 4; ++i)
|
|
Ivan Mahonin |
de1fb3 |
imgPairDraw(&menuLetter.glyphs[i], !(glyphsMask & (1 << i)), ox + i*cw, oy, cw, ch);
|
|
Ivan Mahonin |
7d8000 |
if (glyphsMask)
|
|
Ivan Mahonin |
7d8000 |
imgExDraw(&starttex, ox + cw, oy + ch, 2*cw, ch);
|
|
Ivan Mahonin |
7d8000 |
} else {
|
|
 |
5c4215 |
if (winW*cellHeight*(rows + 2) < winH*cellWidth*(cols + 4)) {
|
|
 |
5c4215 |
cw = winW/(cols + 4);
|
|
Ivan Mahonin |
7d8000 |
ch = cellHeight*cw/cellWidth;
|
|
Ivan Mahonin |
7d8000 |
} else {
|
|
 |
5c4215 |
ch = winH/(rows + 2);
|
|
Ivan Mahonin |
7d8000 |
cw = cellWidth*ch/cellHeight;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
 |
5c4215 |
ox = (winW - cw*cols)/2;
|
|
 |
5c4215 |
oy = (winH - ch*rows)/2;
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
// draw buttons
|
|
Ivan Mahonin |
7d8000 |
imgExDraw(&backtex[back], ox - 2*cw, oy - ch, 2*cw, ch);
|
|
 |
5c4215 |
imgExDraw(&hinttex, ox + cols*cw, oy + rows*ch, 2*cw, ch);
|
|
 |
5c4215 |
imgExDraw(&sndtex[mute], ox + cols*cw, oy - ch, 2*cw, ch);
|
|
Ivan Mahonin |
de1fb3 |
for(int i = 0; i < 3; ++i) imgExResample(&sndtex[i], cw, ch);
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
// draw cells
|
|
 |
5c4215 |
for(int r = 0; r < rows; ++r)
|
|
 |
5c4215 |
for(int c = 0; c < cols; ++c) {
|
|
Ivan Mahonin |
7d8000 |
Cell *cell = &board[r][c];
|
|
Ivan Mahonin |
7d8000 |
if (!cell->g) continue;
|
|
Ivan Mahonin |
de1fb3 |
int hilight = (r == hover.r && c == hover.c)
|
|
Ivan Mahonin |
de1fb3 |
|| (r == selected.r && c == selected.c)
|
|
Ivan Mahonin |
86bfaf |
|| (hintLetter && hintLetter == cell->l);
|
|
Ivan Mahonin |
de1fb3 |
imgPairDraw(cell->g, hilight, ox + c*cw, oy + r*ch, cw, ch);
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|
|
Ivan Mahonin |
7d8000 |
// draw tracks
|
|
Ivan Mahonin |
de1fb3 |
int lw = cw/6;
|
|
Ivan Mahonin |
de1fb3 |
if (lw < 1) lw = 1;
|
|
Ivan Mahonin |
7d8000 |
XSetForeground(dpy, gc, 0xff0000);
|
|
Ivan Mahonin |
de1fb3 |
XSetLineAttributes(dpy, gc, lw, LineSolid, CapRound, JoinRound);
|
|
Ivan Mahonin |
7d8000 |
for(int i = 0; i < tracksCount; ++i) {
|
|
Ivan Mahonin |
7d8000 |
Track *t = &tracks[i];
|
|
Ivan Mahonin |
7d8000 |
XPoint p[4];
|
|
Ivan Mahonin |
7d8000 |
for(int j = 0; j < t->len; ++j) {
|
|
Ivan Mahonin |
7d8000 |
p[j].x = ox + t->p[j].c*cw + cw/2;
|
|
Ivan Mahonin |
7d8000 |
p[j].y = oy + t->p[j].r*ch + ch/2;
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
XDrawLines(dpy, drw, gc, p, t->len, CoordModeOrigin);
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
}
|
|
Ivan Mahonin |
7d8000 |
|