summaryrefslogtreecommitdiff
path: root/main.f90
blob: b7052bbd2d1271142c8f12c20e19b269fc432418 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
program fetris
use m_game
use m_screen
use m_piece
use m_constants
use bgi
implicit none

type(game)::g
type(piece)::new_p
logical::playing, loser
logical::redraw
integer::last_score

integer(kind=8)::count_rate, count_now
real(kind=8)::current_time, last_update

    call init_random()

    call init()
    
    g = new_game()
    g%falling = new_piece()
    g%piece_stuck = .FALSE.
    
    g%waiting = new_piece()
    
    call system_clock(count_rate=count_rate)
    
    playing = .TRUE.
    loser = .FALSE.
    last_update = 0
    last_score = -1
    call draw_score(g)
    call draw_next(g)
    
    do while(playing)
    
        call system_clock(count=count_now)
        current_time = real(count_now, 8)/real(count_rate,8)
        redraw = .FALSE.
    
        if(current_time - last_update .GT. UPDATE_SECONDS) then
            last_update = current_time
            call move_piece(g)
            redraw = .TRUE.
        else
            !call MilliSleep(50)
        end if
    
        if(g%piece_stuck) then
            
            last_score = g%score
            call check_rows(g)
        
            !new_p = new_piece()
            if(.NOT. check_piece(g, g%waiting, g%waiting%r, g%waiting%c)) then
                loser = .TRUE.
                playing = .FALSE.
                call clear_keys()
                exit
            else
                g%falling = g%waiting
                g%piece_stuck = .FALSE.
                call clear_keys()
                
                g%waiting = new_piece()
                call draw_next(g)
            end if
        end if
        
        if(kbhit() .NE. 0) then
            select case (getch())
                case (KEY_LEFT)
                    call move_piece(g, LEFT)
                    redraw = .TRUE.
                case (KEY_RIGHT)
                    call move_piece(g, RIGHT)
                    redraw = .TRUE.
                case (KEY_DOWN)
                    call move_piece(g, DOWN)
                    redraw = .TRUE.
                case (KEY_UP)
                    call rotate_piece(g)
                    redraw = .TRUE.
                case (ichar('q'), ichar('Q'))
                    playing = .FALSE.
            end select
        end if
        
        if(redraw) then
            call draw_board(g)
            if(g%score .NE. last_score) then
                call draw_score(g)
                last_score = g%score
            end if
        end if
    
    end do
    
    if(loser) then
        call clear_keys()
        call show_loss(g%score)
    end if
    
    call shutdown()

contains

    subroutine init_random()
    implicit none
    INTEGER :: i, n, clock
    INTEGER, DIMENSION(:), ALLOCATABLE :: seed

        CALL RANDOM_SEED(size = n)
        ALLOCATE(seed(n))

        CALL SYSTEM_CLOCK(COUNT=clock)

        seed = clock + 37 * (/ (i - 1, i = 1, n) /)
        CALL RANDOM_SEED(PUT = seed)

        DEALLOCATE(seed)
    end subroutine init_random

    subroutine clear_keys()
    use bgi
    implicit none
    
    integer::ignored
    
        do while(kbhit() .NE. 0)
            ignored = getch()
        end do
        
    end subroutine clear_keys
    
end program fetris