środa, 12 czerwca 2013

Brainfuck interpreter in Flex/Bison and C

Recently I've had to write Brainfuck interpreter using Flex and Biso 

Brainfuck.l:
/*gedit
*/
%{
#include <stdlib.h>
#include <stdio.h>
#include "Node.h"
#include "Brainfuck.h"
%}
%%
[\-\[\]\<\>\+\,\.] { return *yytext; }
[\n] { return END; }
.
%%
/*main() { printf("%d", yylex());}*/
Brainfuck.y
/*gedit
*/
%{
#include <stdlib.h>
#include <stdio.h>
#include "Node.h"
#define MAX_MEMORY 30000
#define INNER 0
#define LOOP 1

unsigned static char tab[MAX_MEMORY]; //static, no need to initialize with zero
int pointer;
Node *parse(int op, Node *prev, Node *next);
void delete_node(Node *p);
void yyerror(char *string);
int execute(Node *p);
int yylex(void);
%}
%union{
Node *nodePointer;
}
%type <nodePointer> instruction instruction_list
%token END
%%
program:
 instruction_list END { execute($1); delete_node($1); exit(0); }
;
instruction_list:
 instruction { $$ = $1; }
| instruction_list instruction { $$ = parse(INNER, $1, $2); }
;
instruction:
 '<' { $$ = parse('<', NULL, NULL); }
| '>' { $$ = parse('>', NULL, NULL); }
| ',' { $$ = parse(',', NULL, NULL); }
| '.' { $$ = parse('.', NULL, NULL); }
| '+' { $$ = parse('+', NULL, NULL); }
| '-' { $$ = parse('-', NULL, NULL); }
| '[' instruction_list ']' { $$ = parse(LOOP, $2, NULL); }
;
%%
Node *parse(int op, Node *prev, Node *next) {
Node *node;
if ((node = (Node *)malloc(sizeof(Node))) == NULL)
yyerror("Out of memory.");
node->op = op;
node->prev  = prev;
node->next = next;
return node;
}
void delete_node(Node *p){
if (p == NULL)
return;
delete_node(p->next);
delete_node(p->prev);
free(p);
}
void yyerror(char *string){
printf("%s\n", string);
}
int execute(Node *p){
if (p == NULL)
return 0;
switch(p->op){
case '>':
pointer++;
if (pointer >= MAX_MEMORY) {
yyerror("Pointer out of bounds.");
return -1;
}
return 0;
case '<':
pointer--;
if (pointer < 0){
yyerror("Pointer out of bounds.");
return -1;
}
return 0;
case '+':
tab[pointer]++; return 0;
case '-':
tab[pointer]--; return 0;
case '.':
putchar(tab[pointer]); return 0;
case ',':
tab[pointer] = getchar(); return 0;
case LOOP:
while (tab[pointer])
execute(p->prev);
execute(p->next);
return 0;
case INNER:
execute(p->prev);
execute(p->next);
return 0;
}
return -1;
}

int main()
{
pointer = 0;
yyparse();

Node.h
/*
*/
typedef struct Node{
int op;
void *prev;
void *next;
}Node; 

Makefile:
OBJS = Brainfuck.y.o Brainfuck.l.o
GCC = gcc

Brainfuck: $(OBJS)
@echo "   >> Compile and Link"
$(GCC) -o Brainfuck $(OBJS) -lfl
Brainfuck.l.o: Brainfuck.l.c
@echo "   >> Compile Flex generated file"
$(GCC) -c Brainfuck.l.c -o Brainfuck.l.o
Brainfuck.l.c: Brainfuck.l
@echo "   >> Use Flex"
flex Brainfuck.l
mv lex.yy.c Brainfuck.l.c
Brainfuck.y.o: Brainfuck.y.c
@echo "   >> Compile Bison generated file"
$(GCC) -c Brainfuck.y.c -o Brainfuck.y.o
Brainfuck.y.c: Brainfuck.y
@echo "   >> Use Bison"
bison -d Brainfuck.y
@echo "   >> Rename results"
mv Brainfuck.tab.h Brainfuck.h
mv Brainfuck.tab.c Brainfuck.y.c
Brainfuck.y.o: Node.h
clean:
rm *.o Brainfuck.h Brainfuck.l.c Brainfuck.y.c Brainfuck 

wtorek, 12 lutego 2013

Play Tibia against bots? Sure!

Recently I've been out of hosting OTSes. I've played some Dota2, Leauge of Legends, HoN, etc.
I discovered that one thing today OTSes are missing is player (bot) AI.
How funny it would be to just join some war server and play against bots to train your PVP or just join it with your guild to train some tactics?

I started to edit source and create lua scripts to support such feature.
So far I've finished:

  • walking around
  • healing/drinking potions
  • going from point to point with path finding algorithms
  • leaving spawn (protection zone)
  • attacking players who attacked bot


Still, there are plenty things to be done:

  • running away from target
  • keeping distance from the target (mages/palladins)
  • finding potential targets
  • better targetting (i.e. players with lower health, not full hp)
  • casting offensive and utility spells depending of the situation
  • using items
  • using runes
I hope that it will be possible to release some early beta in the end of April, and this idea in Open Tibia world will gain some applause.

wtorek, 5 lutego 2013

Erlang :)

I was writing OpenTibia status checker in Java for my upcomming open tibia sever list. The thing is I wanted to refresh all servers as fast as possible.
Application done with Java, Threads Pool, 32 active threads on 16 cores machine: 7 minutes.
With Erlang I'm able to fetch statuses of 360 servers in less than.. 35 seconds. Nice, hey?

I decided to give Erlang a try - just check the figures they offer to Erlang programmers.