Welcome, guest! Login / Register - Why register?
Psst.. new poll here.
Psst.. new forums here.
Microsoft is blocking us again (TY IP Reputation!) so dont bother with any of their useless mail servers here and just use oauth login instead. Thank the nice Russians for causing that. :)

Paste

Pasted as C# by AlMag ( 15 years ago )
open System
open System.Windows.Forms
open System.Drawing
open Microsoft.FSharp.Control.CommonExtensions
open System.Collections.Generic
open System.IO

let SS = DateTime.Now
     
let Sqr a = a*a

let Dist (a:(int*int)) (b:(int*int)) =
    Sqr ((fst a)-(fst b)) + Sqr ((snd a)-(snd b))

let Vect x1 y1 x2 y2 x3 y3 =
    let (dx1, dy1) = (x1-x2, y1-y2)
    let (dx2, dy2) = (x3-x2, y3-y2)
    match (dx1*dy2-dx2*dy1) with
        | p when p<0 -> -1
        | p when p>0 -> +1
        | _ -> 0

let isInter xx yy rr x1 y1 x2 y2 =
    let mutable d = 1000000000
    d <- min d (Dist (xx, yy) (x1, y1))
    d <- min d (Dist (xx, yy) (x2, y2))
    if ((Vect xx yy x1 y1 x2 y2) * (Vect xx yy x2 y2 x1 y1) > 0) then
        let a = y2-y1
        let b = x1-x2
        let c = -a*x1-b*y1
        Sqr (a*xx+b*yy+c) <= (Sqr rr)*(Sqr a + Sqr b)
    else
        d <= Sqr rr

let isIntersects xx yy rr x y w h =
    (isInter xx yy rr x y (x+w) y ||
     isInter xx yy rr (x+w) y (x+w) (y+h) ||
     isInter xx yy rr (x+w) (y+h) x (y+h) ||
     isInter xx yy rr x (y+h) x y)

let dCell = 20
let dCirc = 11
    
type IPaintObject =
    abstract Paint : Graphics -> unit
    abstract Recalc : float -> unit

type DelegateLoad = delegate of (string) -> (int[][]*ResizeArray<IPaintObject>*int)
    
let po = new ResizeArray<IPaintObject>()

type SmoothForm(dx:int, dy:int, _path:string) as x =
    inherit Form()
    do x.DoubleBuffered <- true

    let mutable left = 0
    let mutable down = 0
    let mutable right = 0
    let mutable up = 0
    let mutable need = 0
    let mutable path = _path
    let mutable currLevel = 0
    let mutable complete = 0
    let mutable (dd:DelegateLoad) = null
    let mutable death = 0
    let mutable loading = 0

    let mutable Map = null

    let d = new Dictionary<int, double*double>()

    member x.Load(_map:int[][], obj, _need) = 
        Map <- _map
        po.Clear()
        for o in obj do
            po.Add o
        need <- _need
        x.Init()

    member x.LoadNext() =
        currLevel <- currLevel + 1
        if (File.Exists(path+""+"L"+currLevel.ToString()+".txt") = false) then
            complete <- 1
        else
            x.Loading <- 2
            x.Load(dd.Invoke(path+""+"L"+currLevel.ToString()+".txt"))
            x.Loading <- 0
        x.Invalidate()


    member x.Init() =
        left <- 0
        down <- 0
        right <- 0
        up <- 0

        let mm = Map |> Array.map(fun x -> x |> Array.max) |> Array.max
        let xMin = Array.create (mm+1) 1000.0
        let xMax = Array.create (mm+1) 0.0
        let yMin = Array.create (mm+1) 1000.0
        let yMax = Array.create (mm+1) 0.0
        for i = 0 to x.rows-1 do
            for j = 0 to x.cols-1 do
                if (Map.[i].[j]>0) then
                    let p = Map.[i].[j]
                    xMin.[p] <- min (xMin.[p]) (float (j*dx))
                    xMax.[p] <- max (xMax.[p]) (float ((j+1)*dx))
                    yMin.[p] <- min (yMin.[p]) (float (i*dy))
                    yMax.[p] <- max (yMax.[p]) (float ((i+1)*dy))
        d.Clear()
        for i in [1..mm] do
            d.Add(i, ((xMin.[i]+xMax.[i])/2., (yMin.[i]+yMax.[i])/2.))

    member x.FuncLoad with get() = dd and set(v) = (dd <- v)

    member x.Complete = complete
    member x.Death with get() = death and set(v) = (death <- v)
    member x.Path with get() = path and set(v) = (path <- v)
    member x.map = Map
    member x.Saves = d
    member x.needGather = need
    member x.Loading with get() = loading and set(v) = (loading <- v)

    member x.Left with get() = left and set(v) = (left <- v)
    member x.Right with get() = right and set(v) = (right <- v)
    member x.Down with get() = down and set(v) = (down <- v)
    member x.Up with get() = up and set(v) = (up <- v)        

    member x.DX = dx
    member x.DY = dy
    member x.rows = (Map |> Array.length)
    member x.cols = (Map.[0] |> Array.length)

let form = new SmoothForm(Text="F# The world hardest game",  Visible=true, TopMost=true,
                            Width=22*dCell+8, Height=14*dCell+33,
                            dx=dCell, dy=dCell,
                            FormBorderStyle=FormBorderStyle.FixedSingle,
                            _path = @"C:Documents and SettingsslimМои документыVisual Studio 2010ProjectsTCFS_Console")

form.KeyDown
    |> Event.filter(fun args -> (args.KeyValue >= 37) && (args.KeyValue <= 40)) 
    |> Event.add (fun args ->
        match (args.KeyCode) with
            | Keys.Down -> form.Down <- 1
            | Keys.Left -> form.Left <- 1
            | Keys.Right -> form.Right <- 1
            | Keys.Up -> form.Up <- 1     
        )

form.KeyUp
    |> Event.filter(fun args -> (args.KeyValue >= 37) && (args.KeyValue <= 40))
    |> Event.add (fun args ->
        match (args.KeyCode) with
            | Keys.Down -> form.Down <- 0
            | Keys.Left -> form.Left <- 0
            | Keys.Right -> form.Right <- 0
            | Keys.Up -> form.Up <- 0
        )

form.Paint.Add(fun arg ->
    let g = arg.Graphics
    if (form.Complete = 0) then
        if (form.Loading = 0) then
            for i=0 to form.rows-1 do
                for j=0 to form.cols-1 do
                    match (form.map.[i].[j], (i+j)%2) with
                        | (-1, _) -> g.FillRectangle(Brushes.DarkViolet, j*form.DX, i*form.DY, form.DX, form.DY)
                        | ( 0, 0) -> g.FillRectangle(Brushes.White, j*form.DX, i*form.DY, form.DX, form.DY)
                        | ( 0, 1) -> g.FillRectangle(Brushes.LightGray, j*form.DX, i*form.DY, form.DX, form.DY)
                        | ( p, _) when p>0 -> g.FillRectangle(Brushes.LightGreen, j*form.DX, i*form.DY+1, form.DX, form.DY)
                    if (i>0 && (form.map.[i].[j]>=0 && form.map.[i-1].[j]<0
                            ||  form.map.[i].[j]<0 && form.map.[i-1].[j]>=0)) then
                        g.DrawLine(new Pen(Color.Black, float32 2), j*form.DX, i*form.DY, (j+1)*form.DX, i*form.DY)
                    if (j>0 && (form.map.[i].[j]>=0 && form.map.[i].[j-1]<0
                            ||  form.map.[i].[j]<0 && form.map.[i].[j-1]>=0)) then
                        g.DrawLine(new Pen(Color.Black, float32 2), j*form.DX, i*form.DY, j*form.DX, (i+1)*form.DY)
            for obj in po do
                obj.Recalc((DateTime.Now-SS).TotalSeconds)
                obj.Paint(g)
            async { do! Async.Sleep(10)
                    form.Invalidate() } |> Async.Start
        else
            if (form.Loading = 1) then
                form.LoadNext()
    else
        g.FillRectangle(Brushes.Magenta, 0, 0, form.Width, form.Height);
        g.DrawString("Deaths: " + form.Death.ToString(), new Font(FontFamily.GenericMonospace, float32 32.), Brushes.Black, float32 20., float32 100.)
)

type RedSquare(xx:int, yy:int, ww:int, hh:int, speed:int) =
    let mutable xCoord = float xx
    let mutable yCoord = float yy
    let mutable width = ww
    let mutable height = hh
    let mutable dying = 0
    let mutable gather = 0
    let mutable last = 0.0
    let mutable xSave = float xx
    let mutable ySave = float yy
    let mutable lastSave = 1

    member rs.X with get() = int xCoord and set(v) = (xCoord <- v)
    member rs.Y with get() = int yCoord and set(v) = (yCoord <- v)
    member rs.W with get() = width and set(v) = (width <- v)
    member rs.H with get() = height and set(v) = (height <- v)
    member rs.Got with get() = gather
    member rs.isDying with get() = (dying>0)

    member rs.Die() =
        if (dying = 0) then
            dying <- 1
            gather <- 0
            form.Death <- form.Death+1
    member rs.Add() =
        gather <- gather+1

    interface IPaintObject with
        member obj.Paint(g) =
            let rect = 
                match (dying) with
                    | 0 -> Rectangle(x=int xCoord-width/2, y=int yCoord-height/2, width=width, height=height)
                    | p when 2*p>=ww ->
                                        xCoord <- xSave
                                        yCoord <- ySave
                                        dying <- 0
                                        Rectangle(x=int xCoord-width/2, y=int yCoord-height/2, width=width, height=height)
                    | p ->
                            dying <- dying+1
                            Rectangle(x=int xCoord-width/2+p, y=int yCoord-height/2+p, width=width-p-p, height=height-p-p)
            g.FillRectangle(Brushes.Red, rect)
            g.DrawRectangle(new Pen(Color.Black, float32 2), rect)
        member obj.Recalc(T) =
            let t = T-last
            let mutable xOld = 0.0
            let mutable yOld = 0.0

            if (dying=0) then
                xOld <- xCoord
                yOld <- yCoord
                xCoord <- xCoord - ((float (form.Left))*(float speed)*t)
                if (form.map.[int (yCoord-float height/2.)/dCell].[int (xCoord-float width/2.)/dCell]<0 ||
                    form.map.[int (yCoord+float height/2.)/dCell].[int (xCoord-float width/2.)/dCell]<0) then
                    xCoord <- xOld
                    yCoord <- yOld

                xOld <- xCoord
                yOld <- yCoord
                xCoord <- xCoord + ((float (form.Right))*(float speed)*t)
                if (form.map.[int (yCoord-float height/2.)/dCell].[int (xCoord+float width/2.)/dCell]<0 ||
                    form.map.[int (yCoord+float height/2.)/dCell].[int (xCoord+float width/2.)/dCell]<0) then
                    xCoord <- xOld
                    yCoord <- yOld

                xOld <- xCoord
                yOld <- yCoord
                yCoord <- yCoord - ((float (form.Up))*(float speed)*t)
                if (form.map.[int (yCoord-float height/2.)/dCell].[int (xCoord-float width/2.)/dCell]<0 ||
                    form.map.[int (yCoord-float height/2.)/dCell].[int (xCoord+float width/2.)/dCell]<0) then
                    xCoord <- xOld
                    yCoord <- yOld

                xOld <- xCoord
                yOld <- yCoord
                yCoord <- yCoord + ((float (form.Down))*(float speed)*t)
                if (form.map.[int (yCoord+float height/2.)/dCell].[int (xCoord-float width/2.)/dCell]<0 ||
                    form.map.[int (yCoord+float height/2.)/dCell].[int (xCoord+float width/2.)/dCell]<0) then
                    xCoord <- xOld
                    yCoord <- yOld

                let rr = int yCoord/dCell
                let cc = int xCoord/dCell
                if (form.map.[rr].[cc] > lastSave && form.map.[rr].[cc] <> form.Saves.Count) then
                    lastSave <- form.map.[rr].[cc]
                    xSave <- fst form.Saves.[lastSave]
                    ySave <- snd form.Saves.[lastSave]

                if (form.map.[rr].[cc] = form.Saves.Count && gather = form.needGather) then
                    form.Loading <- 1
                    
            last <- T

type BlueCircle(xx:int, yy:int, rr:int, speed:int, segments:(int*int)[]) =
    let len = segments |> Array.length

    let mutable X = xx
    let mutable Y = yy
       
    member bc.Stable with get() = (bc.TotalDist < 1e-8)
    member bc.Speed with get() = float speed
    member bc.Dists = segments |> Array.map(fun (dx, dy) -> Math.Sqrt(float(dx*dx+dy*dy)))
    member bc.TotalDist = bc.Dists |> Array.sum
    member bc.TotalTime = bc.TotalDist/bc.Speed

    interface IPaintObject with
        member obj.Paint(g) =
            let rect = Rectangle(x=X-rr, y=Y-rr, width=rr+rr, height=rr+rr)
            g.FillEllipse(Brushes.Blue, rect)
            g.DrawEllipse(Pens.Black, rect)
        member bc.Recalc(tt) =
            if (bc.Stable=false) then
                let mutable t1 = tt�.TotalTime
                let mutable ind = 0
                X <- xx
                Y <- yy
                while (ind<len-1 && t1*bc.Speed>=bc.Dists.[ind]) do
                    X <- X + (fst segments.[ind])
                    Y <- Y + (snd segments.[ind])
                    t1 <- t1-bc.Dists.[ind]/bc.Speed
                    ind <- ind+1
            
                let (dx, dy) = (((float (fst segments.[ind]))/(bc.Dists.[ind])),
                                ((float (snd segments.[ind]))/(bc.Dists.[ind])))
                X <- X + int (dx*t1*bc.Speed)
                Y <- Y + int (dy*t1*bc.Speed)

                let rs = seq { for obj in po do
                                    match obj with
                                        | :? RedSquare as p ->
                                            yield p 
                                        | _ -> yield! Seq.empty
                                } |> Seq.head

                if (isIntersects X Y rr (rs.X-rs.W/2) (rs.Y-rs.H/2) (rs.W) (rs.H)) then
                    rs.Die()

type YellowCircle(xx:int, yy:int, rr:int, tr:float) =
    let mutable XX = 0
    let mutable Disable = false

    member yc.isDead with get() = Disable and set(v) = (Disable <- v)
    member yc.Take() =
        yc.isDead <- true

    interface IPaintObject with
        member obj.Paint(g) =
            if (not Disable) then
                let rect = Rectangle(x=xx-rr+XX, y=yy-rr, width=rr+rr-XX-XX, height=rr+rr)
                g.FillEllipse(Brushes.Yellow, rect)
                g.DrawEllipse(Pens.Black, rect)
        member yc.Recalc(tt:float) =
            let rs =  seq { for obj in po do
                                match obj with
                                    | :? RedSquare as p ->
                                        yield p 
                                    | _ -> yield! Seq.empty
                            } |> Seq.head
            if (not Disable && rs.isDying=false) then
                let mutable t = tt%tr
                if (t*2.>tr) then t <- tr-t
                XX <- int (((float rr)/(tr/2.))*t)

                if (isIntersects xx yy rr (rs.X-rs.W/2) (rs.Y-rs.H/2) (rs.W) (rs.H)) then
                    yc.Take()
                    rs.Add()
            else
                if (Disable && rs.isDying=true) then
                    Disable <- false

// Ф-ция парсит файл по заданому пути, выковыривая параметры уровня
let LoadLevel _path =
    let pp = new ResizeArray<IPaintObject>()

    let data = File.ReadAllLines(_path) |> Array.toSeq;
    let tmp = 0
    let tmpD = 0.0
    let nm = (data |> Seq.head).Split([|' '|])
    let (n, m) = (Int32.Parse(nm.[0]), Int32.Parse(nm.[1]))
    let L1 = data
             |> Seq.skip 1
             |> Seq.take n
             |> Seq.toArray
             |> Array.map(fun x -> x.Split([|' '|]) |> Array.filter(fun x -> Int32.TryParse(x, ref tmp)) |> Array.map(fun x -> Int32.Parse(x)))

    let lbc = Int32.Parse(data
             |> Seq.skip (1+n)
             |> Seq.head)

    let bc = data
             |> Seq.skip 1
             |> Seq.skip n
             |> Seq.skip 1
             |> Seq.take lbc
             |> Seq.toArray
             |> Array.map(fun x ->
                    let b = x.Replace('.', ',').Split([|' '|]) |> Array.filter(fun x -> Double.TryParse(x, ref tmpD)) |> Array.map(fun x -> Double.Parse(x))
                    let c = int (b.[4])
                    let move = 
                        [|
                            for i in [0..c-1] do
                                yield (int(b.[5+2*i]*(float)dCell), int(b.[5+2*i+1]*(float)dCell))
                        |]
                    new BlueCircle(int (b.[0]*(float)dCell), int (b.[1]*(float)dCell), int(b.[2]*(float)dCirc), int(b.[3]*(float)dCell), move)
                )

    let ly = Int32.Parse(data
             |> Seq.skip 1
             |> Seq.skip n
             |> Seq.skip 1
             |> Seq.skip lbc
             |> Seq.head)

    let y = data
             |> Seq.skip 1
             |> Seq.skip n
             |> Seq.skip 1
             |> Seq.skip lbc
             |> Seq.skip 1
             |> Seq.take ly
             |> Seq.toArray
             |> Array.map(fun x ->
                    let b = x.Replace('.', ',').Split([|' '|]) |> Array.filter(fun x -> Double.TryParse(x, ref tmpD)) |> Array.map(fun x -> Double.Parse(x))
                    new YellowCircle(int (b.[0]*(float)dCell), int (b.[1]*(float)dCell), int(b.[2]*(float)dCirc), (b.[3]))
                )

    let rs = data         
             |> Seq.skip 1
             |> Seq.skip n
             |> Seq.skip 1
             |> Seq.skip lbc
             |> Seq.skip 1
             |> Seq.skip ly
             |> Seq.take 1
             |> Seq.toArray
             |> Array.map(fun x ->
                    let b = x.Replace('.', ',').Split([|' '|]) |> Array.filter(fun x -> Double.TryParse(x, ref tmpD)) |> Array.map(fun x -> Double.Parse(x))
                    new RedSquare(int (b.[0]*(float)dCell), int (b.[1]*(float)dCell), int(b.[2]), int(b.[3]), int(b.[4]*(float dCell)))
             )
             |> Array.toSeq
             |> Seq.head
    for obj in bc do
        pp.Add obj

    for obj in y do
        pp.Add obj

    pp.Add rs
    (L1, pp, ly)

form.FuncLoad <- new DelegateLoad(LoadLevel)
form.LoadNext()

form.Show()

#if COMPILED
[<STAThread>]
do Application.Run(form)
#endif

 

Revise this Paste

Children: 31587
Your Name: Code Language: